From 18cf45e613f39a41b75626fef1c59537112df02b Mon Sep 17 00:00:00 2001 From: Jordan Brockopp Date: Tue, 11 Feb 2020 13:47:00 -0600 Subject: [PATCH] feat: add validate logic for plugin (#7) * feat: add validate logic for kubernetes flags * feat: add validate logic for config flags --- cmd/vela-kubernetes/config.go | 51 ++++++++++++++++ cmd/vela-kubernetes/config_test.go | 81 ++++++++++++++++++++++++++ cmd/vela-kubernetes/kubernetes.go | 43 ++++++++++++++ cmd/vela-kubernetes/kubernetes_test.go | 62 ++++++++++++++++++++ cmd/vela-kubernetes/main.go | 59 ++++++++++++++++++- cmd/vela-kubernetes/plugin.go | 19 +++++- cmd/vela-kubernetes/plugin_test.go | 50 +++++++++++++++- 7 files changed, 361 insertions(+), 4 deletions(-) create mode 100644 cmd/vela-kubernetes/config.go create mode 100644 cmd/vela-kubernetes/config_test.go create mode 100644 cmd/vela-kubernetes/kubernetes.go create mode 100644 cmd/vela-kubernetes/kubernetes_test.go diff --git a/cmd/vela-kubernetes/config.go b/cmd/vela-kubernetes/config.go new file mode 100644 index 0000000..8e775ff --- /dev/null +++ b/cmd/vela-kubernetes/config.go @@ -0,0 +1,51 @@ +// Copyright (c) 2020 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package main + +import ( + "fmt" + "time" + + "github.com/sirupsen/logrus" +) + +// Config represents the plugin configuration for Kubernetes config information. +type Config struct { + // Kubernetes files or directories to apply + Files []string + // new container images from files to apply + Images []string + // Kubernetes resources to watch status of + Statuses []string + // total time allowed to watch Kubernetes resources + Timeout time.Duration +} + +// Validate verifies the Config is properly configured. +func (c *Config) Validate() error { + logrus.Trace("validating config configuration") + + // verify files are provided + if len(c.Files) == 0 { + return fmt.Errorf("no config files provided") + } + + // verify images are provided + if len(c.Images) == 0 { + return fmt.Errorf("no config images provided") + } + + // verify statuses are provided + if len(c.Statuses) == 0 { + return fmt.Errorf("no config statuses provided") + } + + // verify timeout is provided + if c.Timeout <= 0 { + return fmt.Errorf("no config timeout provided") + } + + return nil +} diff --git a/cmd/vela-kubernetes/config_test.go b/cmd/vela-kubernetes/config_test.go new file mode 100644 index 0000000..64e0933 --- /dev/null +++ b/cmd/vela-kubernetes/config_test.go @@ -0,0 +1,81 @@ +// Copyright (c) 2020 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package main + +import ( + "testing" + "time" +) + +func TestKubernetes_Config_Validate(t *testing.T) { + // setup types + c := &Config{ + Files: []string{"files"}, + Images: []string{"images"}, + Statuses: []string{"statuses"}, + Timeout: 5 * time.Minute, + } + + err := c.Validate() + if err != nil { + t.Errorf("Validate returned err: %v", err) + } +} + +func TestKubernetes_Config_Validate_NoFiles(t *testing.T) { + // setup types + c := &Config{ + Images: []string{"images"}, + Statuses: []string{"statuses"}, + Timeout: 5 * time.Minute, + } + + err := c.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Config_Validate_NoImages(t *testing.T) { + // setup types + c := &Config{ + Files: []string{"files"}, + Statuses: []string{"statuses"}, + Timeout: 5 * time.Minute, + } + + err := c.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Config_Validate_NoStatuses(t *testing.T) { + // setup types + c := &Config{ + Files: []string{"files"}, + Images: []string{"images"}, + Timeout: 5 * time.Minute, + } + + err := c.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Config_Validate_NoTimeout(t *testing.T) { + // setup types + c := &Config{ + Files: []string{"files"}, + Images: []string{"images"}, + Statuses: []string{"statuses"}, + } + + err := c.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} diff --git a/cmd/vela-kubernetes/kubernetes.go b/cmd/vela-kubernetes/kubernetes.go new file mode 100644 index 0000000..230cbf1 --- /dev/null +++ b/cmd/vela-kubernetes/kubernetes.go @@ -0,0 +1,43 @@ +// Copyright (c) 2020 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package main + +import ( + "fmt" + + "github.com/sirupsen/logrus" +) + +// Kubernetes represents the plugin configuration for Kubernetes information. +type Kubernetes struct { + // cluster configuration to use for interactions + Config string + // cluster context to use for interactions + Context string + // cluster namespace to use for interactions + Namespace string +} + +// Validate verifies the Kubernetes is properly configured. +func (k *Kubernetes) Validate() error { + logrus.Trace("validating kubernetes configuration") + + // verify config is provided + if len(k.Config) == 0 { + return fmt.Errorf("no kubernetes config provided") + } + + // verify context is provided + if len(k.Context) == 0 { + return fmt.Errorf("no kubernetes context provided") + } + + // verify namespace is provided + if len(k.Namespace) == 0 { + return fmt.Errorf("no kubernetes namespace provided") + } + + return nil +} diff --git a/cmd/vela-kubernetes/kubernetes_test.go b/cmd/vela-kubernetes/kubernetes_test.go new file mode 100644 index 0000000..8d4ded8 --- /dev/null +++ b/cmd/vela-kubernetes/kubernetes_test.go @@ -0,0 +1,62 @@ +// Copyright (c) 2020 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package main + +import ( + "testing" +) + +func TestKubernetes_Kubernetes_Validate(t *testing.T) { + // setup types + k := &Kubernetes{ + Config: "config", + Context: "context", + Namespace: "namespace", + } + + err := k.Validate() + if err != nil { + t.Errorf("Validate returned err: %v", err) + } +} + +func TestKubernetes_Kubernetes_Validate_NoConfig(t *testing.T) { + // setup types + k := &Kubernetes{ + Context: "context", + Namespace: "namespace", + } + + err := k.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Kubernetes_Validate_NoContext(t *testing.T) { + // setup types + k := &Kubernetes{ + Config: "config", + Namespace: "namespace", + } + + err := k.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Kubernetes_Validate_NoNamespace(t *testing.T) { + // setup types + k := &Kubernetes{ + Config: "config", + Context: "context", + } + + err := k.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} diff --git a/cmd/vela-kubernetes/main.go b/cmd/vela-kubernetes/main.go index 13145c1..fdca984 100644 --- a/cmd/vela-kubernetes/main.go +++ b/cmd/vela-kubernetes/main.go @@ -6,7 +6,6 @@ package main import ( "os" - "time" "github.com/sirupsen/logrus" @@ -46,6 +45,48 @@ func main() { Usage: "set log level - options: (trace|debug|info|warn|error|fatal|panic)", Value: "info", }, + + // Config Flags + + cli.StringSliceFlag{ + EnvVar: "PARAMETER_FILES,CONFIG_FILES", + Name: "config.files", + Usage: "kubernetes files or directories to interact with", + }, + cli.StringFlag{ + EnvVar: "PARAMETER_IMAGES,CONFIG_IMAGES", + Name: "config.images", + Usage: "container images from files to interact with", + }, + cli.StringSliceFlag{ + EnvVar: "PARAMETER_STATUSES,CONFIG_STATUSES", + Name: "config.statuses", + Usage: "kubernetes resources to watch status on", + }, + cli.DurationFlag{ + EnvVar: "PARAMETER_TIMEOUT,CONFIG_TIMEOUT", + Name: "config.timeout", + Usage: "maximum duration to watch status on kubernetes resources", + Value: 5 * time.Minute, + }, + + // Kubernetes Flags + + cli.StringFlag{ + EnvVar: "PARAMETER_CONFIG,KUBE_CONFIG,KUBERNETES_CONFIG", + Name: "kubernetes.config", + Usage: "kubernetes cluster configuration", + }, + cli.StringFlag{ + EnvVar: "PARAMETER_CONTEXT,KUBE_CONTEXT,KUBERNETES_CONTEXT", + Name: "kubernetes.context", + Usage: "kubernetes cluster context to interact with", + }, + cli.StringFlag{ + EnvVar: "PARAMETER_NAMESPACE,KUBE_NAMESPACE,KUBERNETES_NAMESPACE", + Name: "kubernetes.namespace", + Usage: "kubernetes cluster namespace to interact with", + }, } err := app.Run(os.Args) @@ -83,7 +124,21 @@ func run(c *cli.Context) error { }).Info("Vela Kubernetes Plugin") // create the plugin - p := &Plugin{} + p := &Plugin{ + // config configuration + Config: &Config{ + Files: c.StringSlice("config.files"), + Images: c.StringSlice("config.images"), + Statuses: c.StringSlice("config.statuses"), + Timeout: c.Duration("config.timeout"), + }, + // Kubernetes configuration + Kubernetes: &Kubernetes{ + Config: c.String("kubernetes.config"), + Context: c.String("kubernetes.context"), + Namespace: c.String("kubernetes.namespace"), + }, + } // validate the plugin err := p.Validate() diff --git a/cmd/vela-kubernetes/plugin.go b/cmd/vela-kubernetes/plugin.go index f48038a..2b3302a 100644 --- a/cmd/vela-kubernetes/plugin.go +++ b/cmd/vela-kubernetes/plugin.go @@ -11,7 +11,12 @@ import ( ) // Plugin represents the configuration loaded for the plugin. -type Plugin struct{} +type Plugin struct { + // config arguments loaded for the plugin + Config *Config + // kubernetes arguments loaded for the plugin + Kubernetes *Kubernetes +} // Command formats and outputs the command necessary for // kubectl to manage Kubernetes resources. @@ -35,5 +40,17 @@ func (p *Plugin) Exec() error { func (p *Plugin) Validate() error { logrus.Debug("validating plugin configuration") + // validate config configuration + err := p.Config.Validate() + if err != nil { + return err + } + + // validate Kubernetes configuration + err = p.Kubernetes.Validate() + if err != nil { + return err + } + return nil } diff --git a/cmd/vela-kubernetes/plugin_test.go b/cmd/vela-kubernetes/plugin_test.go index 5523108..7bed507 100644 --- a/cmd/vela-kubernetes/plugin_test.go +++ b/cmd/vela-kubernetes/plugin_test.go @@ -8,6 +8,7 @@ import ( "os/exec" "reflect" "testing" + "time" ) func TestKubernetes_Plugin_Command(t *testing.T) { @@ -38,10 +39,57 @@ func TestKubernetes_Plugin_Exec(t *testing.T) { func TestKubernetes_Plugin_Validate(t *testing.T) { // setup types - p := &Plugin{} + p := &Plugin{ + Config: &Config{ + Files: []string{"files"}, + Images: []string{"images"}, + Statuses: []string{"statuses"}, + Timeout: 5 * time.Minute, + }, + Kubernetes: &Kubernetes{ + Config: "config", + Context: "context", + Namespace: "namespace", + }, + } err := p.Validate() if err != nil { t.Errorf("Validate returned err: %v", err) } } + +func TestKubernetes_Plugin_Validate_NoConfig(t *testing.T) { + // setup types + p := &Plugin{ + Config: &Config{}, + Kubernetes: &Kubernetes{ + Config: "config", + Context: "context", + Namespace: "namespace", + }, + } + + err := p.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +} + +func TestKubernetes_Plugin_Validate_NoKubernetes(t *testing.T) { + // setup types + p := &Plugin{ + Config: &Config{ + Files: []string{"files"}, + Images: []string{"images"}, + Statuses: []string{"statuses"}, + Timeout: 5 * time.Minute, + }, + Kubernetes: &Kubernetes{}, + } + + err := p.Validate() + if err == nil { + t.Errorf("Validate should have returned err") + } +}