From f25a5b24bae090cb418ea33f23ba771b08727248 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 6 Apr 2020 17:06:35 -0400 Subject: [PATCH] upgrade cli package, fix drone 1.x token env variable issue (#127) * upgrade cli package, fix drone 1.x token env variable issue * TOKEN --> PLUGIN_TOKEN * wip test * remove test * add test --- Makefile | 4 +- README.md | 4 +- go.mod | 4 +- go.sum | 19 +++-- main.go | 199 ++++++++++++++++++++++++++------------------------- main_test.go | 76 +++++++++++++++++++- 6 files changed, 197 insertions(+), 109 deletions(-) diff --git a/Makefile b/Makefile index 0d4f5c8..2806015 100644 --- a/Makefile +++ b/Makefile @@ -185,12 +185,12 @@ run : export PLUGIN_NAMESPACE ?= drone-gke-test run : export PLUGIN_REGION ?= $(shell $(gcloud) config get-value compute/region 2>/dev/null) run : export PLUGIN_SECRET_TEMPLATE ?= $(CONFIG_HOME)/.kube.sec.yml run : export PLUGIN_TEMPLATE ?= $(CONFIG_HOME)/.kube.yml +run : export PLUGIN_TOKEN ?= $(shell cat $(test_sa_key_path)) run : export PLUGIN_VARS ?= $(shell cat $(CONFIG_HOME)/vars.json) run : export PLUGIN_VERBOSE ?= 1 run : export PLUGIN_ZONE ?= $(shell $(gcloud) config get-value compute/zone 2>/dev/null) run : export SECRET_APP_API_KEY ?= 123 run : export SECRET_BASE64_P12_CERT ?= "cDEyCg==" -run : export TOKEN ?= $(shell cat $(test_sa_key_path)) run : export docker_repo_name ?= $(docker_default_repo_name) run : export docker_tag ?= $(docker_default_tag) run : export docker_cmd ?= @@ -208,6 +208,7 @@ run : --env PLUGIN_REGION \ --env PLUGIN_SECRET_TEMPLATE \ --env PLUGIN_TEMPLATE \ + --env PLUGIN_TOKEN \ --env PLUGIN_VARS \ --env PLUGIN_VERBOSE \ --env PLUGIN_WAIT_DEPLOYMENTS \ @@ -215,7 +216,6 @@ run : --env PLUGIN_ZONE \ --env SECRET_APP_API_KEY \ --env SECRET_BASE64_P12_CERT \ - --env TOKEN \ --volume $(CONFIG_HOME):$(CONFIG_HOME) \ --workdir $(CONFIG_HOME) \ $(docker_repo_name)/$(docker_image_name):$(docker_tag) $(docker_cmd) diff --git a/README.md b/README.md index f6a0231..7ea1587 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Executing locally from the working directory: cd local-example/ # Set to the path of your GCP service account JSON-formatted key file -export TOKEN=xxx +export JSON_TOKEN_FILE=xxx # Set to your cluster export PLUGIN_CLUSTER=yyy @@ -77,11 +77,11 @@ export SECRET_BASE64_P12_CERT="cDEyCg==" docker run --rm \ -e PLUGIN_CLUSTER \ -e PLUGIN_NAMESPACE \ + -e PLUGIN_TOKEN="$(cat $JSON_TOKEN_FILE)" \ -e PLUGIN_VARS \ -e PLUGIN_ZONE \ -e SECRET_APP_API_KEY \ -e SECRET_BASE64_P12_CERT \ - -e TOKEN="$(cat $TOKEN)" \ -v $(pwd):$(pwd) \ -w $(pwd) \ nytimes/drone-gke --dry-run --verbose diff --git a/go.mod b/go.mod index ef758a1..2949544 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/NYTimes/drone-gke go 1.12 require ( - github.com/stretchr/testify v1.3.0 - github.com/urfave/cli v1.20.0 + github.com/stretchr/testify v1.5.1 + github.com/urfave/cli/v2 v2.2.0 ) diff --git a/go.sum b/go.sum index 7a1f2d0..b15647c 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,21 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 7f0efba..4a48e8f 100644 --- a/main.go +++ b/main.go @@ -16,7 +16,7 @@ import ( "strings" "text/template" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) type token struct { @@ -60,124 +60,127 @@ func main() { } } -func wrapMain() error { - if version == "" { - version = "x.x.x" - } - - if rev == "" { - rev = "[unknown]" - } - - fmt.Printf("Drone GKE Plugin built from %s\n", rev) - - app := cli.NewApp() - app.Name = "gke plugin" - app.Usage = "gke plugin" - app.Action = run - app.Version = fmt.Sprintf("%s-%s", version, rev) - app.Flags = []cli.Flag{ - cli.BoolFlag{ - Name: "dry-run", - Usage: "do not apply the Kubernetes manifests to the API server", - EnvVar: "PLUGIN_DRY_RUN", +func getAppFlags() []cli.Flag { + return []cli.Flag{ + &cli.BoolFlag{ + Name: "dry-run", + Usage: "do not apply the Kubernetes manifests to the API server", + EnvVars: []string{"PLUGIN_DRY_RUN"}, }, - cli.BoolFlag{ - Name: "verbose", - Usage: "dump available vars and the generated Kubernetes manifest, keeping secrets hidden", - EnvVar: "PLUGIN_VERBOSE", + &cli.BoolFlag{ + Name: "verbose", + Usage: "dump available vars and the generated Kubernetes manifest, keeping secrets hidden", + EnvVars: []string{"PLUGIN_VERBOSE"}, }, - cli.StringFlag{ - Name: "token", - Usage: "service account's JSON credentials", - EnvVar: "TOKEN", + &cli.StringFlag{ + Name: "token", + Usage: "service account's JSON credentials", + EnvVars: []string{"PLUGIN_TOKEN", "TOKEN"}, }, - cli.StringFlag{ - Name: "project", - Usage: "GCP project name", - EnvVar: "PLUGIN_PROJECT", + &cli.StringFlag{ + Name: "project", + Usage: "GCP project name", + EnvVars: []string{"PLUGIN_PROJECT"}, }, - cli.StringFlag{ - Name: "zone", - Usage: "zone of the container cluster", - EnvVar: "PLUGIN_ZONE", + &cli.StringFlag{ + Name: "zone", + Usage: "zone of the container cluster", + EnvVars: []string{"PLUGIN_ZONE"}, }, - cli.StringFlag{ - Name: "region", - Usage: "region of the container cluster", - EnvVar: "PLUGIN_REGION", + &cli.StringFlag{ + Name: "region", + Usage: "region of the container cluster", + EnvVars: []string{"PLUGIN_REGION"}, }, - cli.StringFlag{ - Name: "cluster", - Usage: "name of the container cluster", - EnvVar: "PLUGIN_CLUSTER", + &cli.StringFlag{ + Name: "cluster", + Usage: "name of the container cluster", + EnvVars: []string{"PLUGIN_CLUSTER"}, }, - cli.StringFlag{ - Name: "namespace", - Usage: "Kubernetes namespace to operate in", - EnvVar: "PLUGIN_NAMESPACE", + &cli.StringFlag{ + Name: "namespace", + Usage: "Kubernetes namespace to operate in", + EnvVars: []string{"PLUGIN_NAMESPACE"}, }, - cli.StringFlag{ - Name: "kube-template", - Usage: "optional - template for Kubernetes resources, e.g. deployments", - EnvVar: "PLUGIN_TEMPLATE", - Value: ".kube.yml", + &cli.StringFlag{ + Name: "kube-template", + Usage: "optional - template for Kubernetes resources, e.g. deployments", + EnvVars: []string{"PLUGIN_TEMPLATE"}, + Value: ".kube.yml", }, - cli.StringFlag{ - Name: "secret-template", - Usage: "optional - template for Kubernetes Secret resources", - EnvVar: "PLUGIN_SECRET_TEMPLATE", - Value: ".kube.sec.yml", + &cli.StringFlag{ + Name: "secret-template", + Usage: "optional - template for Kubernetes Secret resources", + EnvVars: []string{"PLUGIN_SECRET_TEMPLATE"}, + Value: ".kube.sec.yml", }, - cli.StringFlag{ - Name: "vars", - Usage: "variables to use while templating manifests", - EnvVar: "PLUGIN_VARS", + &cli.StringFlag{ + Name: "vars", + Usage: "variables to use while templating manifests", + EnvVars: []string{"PLUGIN_VARS"}, }, - cli.BoolFlag{ - Name: "expand-env-vars", - Usage: "expand environment variables contents on vars", - EnvVar: "PLUGIN_EXPAND_ENV_VARS", + &cli.BoolFlag{ + Name: "expand-env-vars", + Usage: "expand environment variables contents on vars", + EnvVars: []string{"PLUGIN_EXPAND_ENV_VARS"}, }, - cli.StringFlag{ - Name: "drone-build-number", - Usage: "Drone build number", - EnvVar: "DRONE_BUILD_NUMBER", + &cli.StringFlag{ + Name: "drone-build-number", + Usage: "Drone build number", + EnvVars: []string{"DRONE_BUILD_NUMBER"}, }, - cli.StringFlag{ - Name: "drone-commit", - Usage: "Git commit hash", - EnvVar: "DRONE_COMMIT", + &cli.StringFlag{ + Name: "drone-commit", + Usage: "Git commit hash", + EnvVars: []string{"DRONE_COMMIT"}, }, - cli.StringFlag{ - Name: "drone-branch", - Usage: "Git branch", - EnvVar: "DRONE_BRANCH", + &cli.StringFlag{ + Name: "drone-branch", + Usage: "Git branch", + EnvVars: []string{"DRONE_BRANCH"}, }, - cli.StringFlag{ - Name: "drone-tag", - Usage: "Git tag", - EnvVar: "DRONE_TAG", + &cli.StringFlag{ + Name: "drone-tag", + Usage: "Git tag", + EnvVars: []string{"DRONE_TAG"}, }, - cli.StringSliceFlag{ - Name: "wait-deployments", - Usage: "list of Deployments to wait for successful rollout, using kubectl rollout status", - EnvVar: "PLUGIN_WAIT_DEPLOYMENTS", + &cli.StringSliceFlag{ + Name: "wait-deployments", + Usage: "list of Deployments to wait for successful rollout, using kubectl rollout status", + EnvVars: []string{"PLUGIN_WAIT_DEPLOYMENTS"}, }, - cli.IntFlag{ - Name: "wait-seconds", - Usage: "if wait-deployments is set, number of seconds to wait before failing the build", - EnvVar: "PLUGIN_WAIT_SECONDS", - Value: 0, + &cli.IntFlag{ + Name: "wait-seconds", + Usage: "if wait-deployments is set, number of seconds to wait before failing the build", + EnvVars: []string{"PLUGIN_WAIT_SECONDS"}, + Value: 0, }, - cli.StringFlag{ - Name: "kubectl-version", - Usage: "optional - version of kubectl binary to use, e.g. 1.14", - EnvVar: "PLUGIN_KUBECTL_VERSION", - Value: "", + &cli.StringFlag{ + Name: "kubectl-version", + Usage: "optional - version of kubectl binary to use, e.g. 1.14", + EnvVars: []string{"PLUGIN_KUBECTL_VERSION"}, + Value: "", }, } +} +func wrapMain() error { + if version == "" { + version = "x.x.x" + } + + if rev == "" { + rev = "[unknown]" + } + + fmt.Printf("Drone GKE Plugin built from %s\n", rev) + + app := cli.NewApp() + app.Name = "gke plugin" + app.Usage = "gke plugin" + app.Action = run + app.Version = fmt.Sprintf("%s-%s", version, rev) + app.Flags = getAppFlags() if err := app.Run(os.Args); err != nil { return err } diff --git a/main_test.go b/main_test.go index 06894a7..7b38f4c 100644 --- a/main_test.go +++ b/main_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/urfave/cli" + "github.com/urfave/cli/v2" ) type MockedRunner struct { @@ -540,3 +540,77 @@ func TestPrintTrimmedError(t *testing.T) { printTrimmedError(strings.NewReader("line 1\nline 2\nline 3"), output) assert.Equal(t, "line 3\n", output.String()) } + +func TestTokenParamPrecedence(t *testing.T) { + for _, tst := range []struct { + name string + envToken string + envPluginToken string + + expectedToken string + expectedOk bool + }{ + { + name: "just-plugin-token", + envToken: "", + envPluginToken: "token123", + + expectedOk: true, + expectedToken: "token123", + }, + { + name: "just-token", + envToken: "token456", + envPluginToken: "", + + expectedOk: true, + expectedToken: "token456", + }, + { + name: "both-and-plugin-token-wins", + envToken: "token456", + envPluginToken: "token123", + expectedOk: true, + expectedToken: "token123", + }, + { + name: "missing-token", + envToken: "", + envPluginToken: "", + + expectedOk: false, + expectedToken: "", + }, + } { + t.Run(tst.name, func(t *testing.T) { + os.Clearenv() + + os.Setenv("PLUGIN_REGION", "region-123") + os.Setenv("PLUGIN_CLUSTER", "cluster-123") + + if tst.envToken != "" { + os.Setenv("TOKEN", tst.envToken) + } + + if tst.envPluginToken != "" { + os.Setenv("PLUGIN_TOKEN", tst.envPluginToken) + } + + appErr := (&cli.App{ + Flags: getAppFlags(), + Action: func(ctx *cli.Context) error { + if foundToken := ctx.String("token"); foundToken != tst.expectedToken { + return fmt.Errorf("found token: %s, expected: %s", foundToken, tst.expectedToken) + } + return checkParams(ctx) + }, + }).Run([]string{"run"}) + + if tst.expectedOk && appErr != nil { + t.Fatalf("expected expectedOk, got appErr: %s", appErr) + } else if !tst.expectedOk && appErr == nil { + t.Fatalf("expected failure, got appErr: %s", appErr) + } + }) + } +}