From c8a86873043fac57f67b06a36a0fa58e07c8258b Mon Sep 17 00:00:00 2001 From: Tony Li Date: Tue, 28 Apr 2020 13:56:39 -0700 Subject: [PATCH] Fix skipping templates for Drone 1.x (#132) --- DOCS.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++-- main.go | 49 ++++++++++++++++++++++++++++--- main_test.go | 50 ++++++++++++++++++++++++++++++-- 3 files changed, 172 insertions(+), 9 deletions(-) diff --git a/DOCS.md b/DOCS.md index 2b1f2ec..b48c4bd 100644 --- a/DOCS.md +++ b/DOCS.md @@ -191,7 +191,8 @@ _**default**_ `'.kube.yml'` _**description**_ path to Kubernetes manifest template -_**notes**_ rendered using the Go [`text/template`](https://golang.org/pkg/text/template/) package +_**notes**_ rendered using the Go [`text/template`](https://golang.org/pkg/text/template/) package. +If the file does not exist, set `skip_template` to `true`. _**example**_ @@ -219,6 +220,44 @@ pipeline: # ... ``` +### `skip_template` + +_**type**_ `bool` + +_**default**_ `false` + +_**description**_ parse and apply the Kubernetes manifest template + +_**notes**_ turn off the use of the template, regardless if the file exists or not + +_**example**_ + +```yaml +# .drone.yml + +# Drone 1.0+ +--- +kind: pipeline +# ... +steps: + - name: deploy-gke + image: nytimes/drone-gke + settings: + template: k8s/app.yaml + skip_template: true + # ... + +# Drone 0.8 +--- +pipeline: + # ... + deploy: + image: nytimes/drone-gke + template: k8s/app.yaml + skip_template: true + # ... +``` + ### `secret_template` _**type**_ `string` @@ -227,7 +266,44 @@ _**default**_ `'.kube.sec.yml'` _**description**_ path to Kubernetes [_Secret_ resource](http://kubernetes.io/docs/user-guide/secrets/) manifest template -_**notes**_ rendered using the Go [`text/template`](https://golang.org/pkg/text/template/) package +_**notes**_ rendered using the Go [`text/template`](https://golang.org/pkg/text/template/) package. +If the file does not exist, set `skip_secret_template` to `true`. + +_**example**_ + +```yaml +# .drone.yml + +# Drone 1.0+ +--- +kind: pipeline +# ... +steps: + - name: deploy-gke + image: nytimes/drone-gke + settings: + secret_template: my-templates/secrets.yaml + # ... + +# Drone 0.8 +--- +pipeline: + # ... + deploy: + image: nytimes/drone-gke + secret_template: my-templates/secrets.yaml + # ... +``` + +### `skip_secret_template` + +_**type**_ `bool` + +_**default**_ `false` + +_**description**_ parse and apply the Kubernetes _Secret_ resource manifest template + +_**notes**_ turn off the use of the template, regardless if the file exists or not _**example**_ @@ -243,6 +319,7 @@ steps: image: nytimes/drone-gke settings: secret_template: my-templates/secrets.yaml + skip_secret_template: true # ... # Drone 0.8 @@ -252,6 +329,7 @@ pipeline: deploy: image: nytimes/drone-gke secret_template: my-templates/secrets.yaml + skip_secret_template: true # ... ``` diff --git a/main.go b/main.go index 4a48e8f..117c59d 100644 --- a/main.go +++ b/main.go @@ -104,16 +104,26 @@ func getAppFlags() []cli.Flag { }, &cli.StringFlag{ Name: "kube-template", - Usage: "optional - template for Kubernetes resources, e.g. deployments", + Usage: "template for Kubernetes resources, e.g. deployments", EnvVars: []string{"PLUGIN_TEMPLATE"}, Value: ".kube.yml", }, + &cli.BoolFlag{ + Name: "skip-template", + Usage: "do not parse or apply the Kubernetes template", + EnvVars: []string{"PLUGIN_SKIP_TEMPLATE"}, + }, &cli.StringFlag{ Name: "secret-template", - Usage: "optional - template for Kubernetes Secret resources", + Usage: "template for Kubernetes Secret resources", EnvVars: []string{"PLUGIN_SECRET_TEMPLATE"}, Value: ".kube.sec.yml", }, + &cli.BoolFlag{ + Name: "skip-secret-template", + Usage: "do not parse or apply the Kubernetes Secret template", + EnvVars: []string{"PLUGIN_SKIP_SECRET_TEMPLATE"}, + }, &cli.StringFlag{ Name: "vars", Usage: "variables to use while templating manifests", @@ -204,7 +214,13 @@ func run(c *cli.Context) error { } } - // Use custom kubectl version if provided + // Parse skipping template processing. + err := parseSkips(c) + if err != nil { + return err + } + + // Use custom kubectl version if provided. kubectlVersion := c.String("kubectl-version") if kubectlVersion != "" { kubectlCmd = fmt.Sprintf("%s.%s", kubectlCmdName, kubectlVersion) @@ -351,6 +367,31 @@ func getProjectFromToken(j string) string { return t.ProjectID } +// parseSkips determines which templates will be processed. +// Prior in Drone 0.8 we allowed setting template filenames to an empty string "" to skip processing them. +// As of Drone 1.7, env vars that have an empty string as the value are dropped. +// So we need to use and check the new set of flags to determine if the user wants to skip processing a template file. +func parseSkips(c *cli.Context) error { + if c.Bool("skip-template") { + log("Warning: skipping kube-template because it was set to be ignored\n") + if err := c.Set("kube-template", ""); err != nil { + return err + } + } + if c.Bool("skip-secret-template") { + log("Warning: skipping secret-template because it was set to be ignored\n") + if err := c.Set("secret-template", ""); err != nil { + return err + } + } + + if c.Bool("skip-template") && c.Bool("skip-secret-template") { + return fmt.Errorf("Error: skipping both templates ends the plugin execution\n") + } + + return nil +} + // parseVars parses vars (in JSON) and returns a map func parseVars(c *cli.Context) (map[string]interface{}, error) { // Parse variables. @@ -522,7 +563,7 @@ func renderTemplates(c *cli.Context, templateData map[string]interface{}, secret return nil, fmt.Errorf("Error finding template: %s\n", err) } - log("Warning: skipping optional template %s because it was not found\n", t) + log("Warning: skipping optional secret template %s because it was not found\n", t) continue } diff --git a/main_test.go b/main_test.go index 7b38f4c..aec154a 100644 --- a/main_test.go +++ b/main_test.go @@ -368,6 +368,50 @@ func TestRenderTemplates(t *testing.T) { assert.Error(t, err) } +func TestParseSkips(t *testing.T) { + kubeTemplatePath := "/tmp/drone-gke-tests/.kube.yml" + secretTemplatePath := "/tmp/drone-gke-tests/.kube.sec.yml" + + // Test no skip + set := flag.NewFlagSet("test-set", 0) + set.String("kube-template", kubeTemplatePath, "") + set.String("secret-template", secretTemplatePath, "") + c := cli.NewContext(nil, set, nil) + err := parseSkips(c) + assert.NoError(t, err) + assert.Equal(t, kubeTemplatePath, c.String("kube-template")) + assert.Equal(t, secretTemplatePath, c.String("secret-template")) + + // Test skipping both + set.Bool("skip-template", true, "") + set.Bool("skip-secret-template", true, "") + c = cli.NewContext(nil, set, nil) + err = parseSkips(c) + assert.Error(t, err) + + // Test skip template + kubeSet := flag.NewFlagSet("kube-set", 0) + kubeSet.String("kube-template", kubeTemplatePath, "") + kubeSet.String("secret-template", secretTemplatePath, "") + kubeSet.Bool("skip-template", true, "") + c = cli.NewContext(nil, kubeSet, nil) + err = parseSkips(c) + assert.NoError(t, err) + assert.Empty(t, c.String("kube-template")) + assert.Equal(t, secretTemplatePath, c.String("secret-template")) + + // Test skip template + secretSet := flag.NewFlagSet("secret-set", 0) + secretSet.String("kube-template", kubeTemplatePath, "") + secretSet.String("secret-template", secretTemplatePath, "") + secretSet.Bool("skip-secret-template", true, "") + c = cli.NewContext(nil, secretSet, nil) + err = parseSkips(c) + assert.NoError(t, err) + assert.Equal(t, kubeTemplatePath, c.String("kube-template")) + assert.Empty(t, c.String("secret-template")) +} + func TestPrintKubectlVersion(t *testing.T) { testRunner := new(MockedRunner) testRunner.On("Run", []string{"kubectl", "version"}).Return(nil) @@ -570,8 +614,8 @@ func TestTokenParamPrecedence(t *testing.T) { name: "both-and-plugin-token-wins", envToken: "token456", envPluginToken: "token123", - expectedOk: true, - expectedToken: "token123", + expectedOk: true, + expectedToken: "token123", }, { name: "missing-token", @@ -584,7 +628,7 @@ func TestTokenParamPrecedence(t *testing.T) { } { t.Run(tst.name, func(t *testing.T) { os.Clearenv() - + os.Setenv("PLUGIN_REGION", "region-123") os.Setenv("PLUGIN_CLUSTER", "cluster-123")