Add kubectl/apply, kubectl/create, and kubectl/delete commands. Fixed #170
--- a/ChangeLog Wed Feb 14 00:28:46 2018 -0600
+++ b/ChangeLog Thu Feb 15 01:27:37 2018 -0600
@@ -15,6 +15,7 @@
* Add copies of all VCS environment variables without their prefix as well as
a VCS environment variable. Fixed #164
* Added a new aws/ecr-login task for logging into AWS ECR. Fixed #161
+ * Added kubectl/apply, kubectl/create, and kubectl/delete tasks. Fixed #170 * Write warning, error, and fatal log messages to stderr. Fixed #156
--- a/REFERENCE.md Wed Feb 14 00:28:46 2018 -0600
+++ b/REFERENCE.md Thu Feb 15 01:27:37 2018 -0600
@@ -519,6 +519,72 @@
+An apply task will apply kubernetes manifests to the cluster. +| Name | Required | Default | Description | +| ----------| -------- | ---------- | ----------- | +| context | | | The kubernetes context to use. | +| files | Yes | | The list of manifest files to apply. | +| namespace | | | The kubernetes namespace to use. | +| selector | | | The selector to use. | +### kubectl/create Tasks +A create task will create kubernetes manifests on the cluster. +| Name | Required | Default | Description | +| ----------| -------- | ---------- | ----------- | +| context | | | The kubernetes context to use. | +| files | Yes | | The list of manifest files to apply. | +| namespace | | | The kubernetes namespace to use. | +| selector | | | The selector to use. | +### kubectl/delete Tasks +A delete task will delete kubernetes manifests from the cluster. +| Name | Required | Default | Description | +| ----------| -------- | ---------- | ----------- | +| context | | | The kubernetes context to use. | +| files | Yes | | The list of manifest files to apply. | +| namespace | | | The kubernetes namespace to use. | +| selector | | | The selector to use. | The environment section defines a list of environment variables to set for the run.
--- a/config/tasks.go Wed Feb 14 00:28:46 2018 -0600
+++ b/config/tasks.go Thu Feb 15 01:27:37 2018 -0600
@@ -20,6 +20,7 @@
"bitbucket.org/rw_grim/convey/aws"
"bitbucket.org/rw_grim/convey/docker"
"bitbucket.org/rw_grim/convey/intrinsic"
+ "bitbucket.org/rw_grim/convey/kubectl" "bitbucket.org/rw_grim/convey/tasks"
@@ -32,18 +33,23 @@
+ for taskName, task := range aws.Tasks { + TasksMap["aws/"+taskName] = task for taskName, task := range docker.Tasks {
TasksMap["docker/"+taskName] = task
- for taskName, task := range aws.Tasks {
- TasksMap["aws/"+taskName] = task
// add the intrinsic convey tasks
for taskName, task := range intrinsic.Tasks {
TasksMap["convey/"+taskName] = task
+ // add the kubectl tasks + for taskName, task := range kubectl.Tasks { + TasksMap["kubectl/"+taskName] = task --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/apply.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,51 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/gomol" + "bitbucket.org/rw_grim/convey/state" + "bitbucket.org/rw_grim/convey/tasks" +func (a *Apply) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error { + Namespace: a.Namespace, + return cmd.Execute(name, "apply", logger, env, st) +// New creates a new kubectl/apply task. +func (a *Apply) New() tasks.Task { +// Valid check if the apply task is valid +func (a *Apply) Valid() error { --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/apply_test.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,32 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/sweet" + . "github.com/onsi/gomega" +type applySuite struct{} +func (s *applySuite) TestFilesRequired(t sweet.T) { + Expect(a.Valid()).To(Not(BeNil())) + a = &Apply{Files: []string{"foo.yml"}} + Expect(a.Valid()).To(BeNil()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/command.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,78 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// Package intrinsic contains the intrinsic commands + "github.com/aphistic/gomol" + "bitbucket.org/rw_grim/convey/command" + "bitbucket.org/rw_grim/convey/environment" + "bitbucket.org/rw_grim/convey/state" + "bitbucket.org/rw_grim/convey/yaml" +type CRUDCommand struct { + Context string `yaml:"context"` + Namespace string `yaml:"namespace"` + Files yaml.StringOrSlice `yaml:"files"` + Selector string `yaml:"selector"` +func (c *CRUDCommand) Execute(name, action string, logger *gomol.LogAdapter, env []string, st *state.State) error { + fullEnv := environment.Merge(env, st.GetEnv()) + // if we have a context use it + err := useContext(name, c.Context, logger, env, st.PlanTimeout) + // now build the apply command line + cmd := command.NewGenerator("kubectl", action) + namespace, err := environment.Mapper(c.Namespace, fullEnv) + cmd.Append("-n", namespace) + selector, err := environment.Mapper(c.Selector, fullEnv) + cmd.Append("-l", selector) + for _, file := range c.Files { + realFile, err := environment.Mapper(file, fullEnv) + cmd.Append("-f", realFile) + return command.Run(name, cmd.Command(), st.PlanTimeout) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/context.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,38 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/gomol" + "bitbucket.org/rw_grim/convey/command" + "bitbucket.org/rw_grim/convey/environment" +// useContext calls `kubectl config use-context` for the given context +func useContext(name, context string, logger *gomol.LogAdapter, env []string, timeout time.Duration) error { + realContext, err := environment.Mapper(context, env) + cmdv := []string{"kubectl", "config", "use-context", realContext} + return command.Run(name, cmdv, timeout) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/create.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,51 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/gomol" + "bitbucket.org/rw_grim/convey/state" + "bitbucket.org/rw_grim/convey/tasks" +func (c *Create) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error { + Namespace: c.Namespace, + return cmd.Execute(name, "create", logger, env, st) +// New creates a new kubectl/create task. +func (c *Create) New() tasks.Task { +// Valid check if the apply task is valid +func (c *Create) Valid() error { --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/create_test.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,32 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/sweet" + . "github.com/onsi/gomega" +type createSuite struct{} +func (s *createSuite) TestFilesRequired(t sweet.T) { + Expect(c.Valid()).To(Not(BeNil())) + c = &Create{Files: []string{"foo.yml"}} + Expect(c.Valid()).To(BeNil()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/delete.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,51 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/gomol" + "bitbucket.org/rw_grim/convey/state" + "bitbucket.org/rw_grim/convey/tasks" +func (d *Delete) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error { + Namespace: d.Namespace, + return cmd.Execute(name, "delete", logger, env, st) +// New creates a new kubectl/create task. +func (d *Delete) New() tasks.Task { +// Valid check if the apply task is valid +func (d *Delete) Valid() error { --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/delete_test.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,32 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/sweet" + . "github.com/onsi/gomega" +type deleteSuite struct{} +func (s *deleteSuite) TestFilesRequired(t sweet.T) { + Expect(d.Valid()).To(Not(BeNil())) + d = &Delete{Files: []string{"foo.yml"}} + Expect(d.Valid()).To(BeNil()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/errors.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,25 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + errNoFiles = errors.New("no files specified") --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/kubectl.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,31 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// Package intrinsic contains the intrinsic commands + "bitbucket.org/rw_grim/convey/tasks" + // Tasks is a map of kubectl tasks. + Tasks = map[string]tasks.Task{ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kubectl/kubectl_test.go Thu Feb 15 01:27:37 2018 -0600
@@ -0,0 +1,37 @@
+// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com> +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + "github.com/aphistic/sweet" + junit "github.com/aphistic/sweet-junit" + . "github.com/onsi/gomega" +func TestMain(m *testing.M) { + RegisterFailHandler(sweet.GomegaFail) + sweet.Run(m, func(s *sweet.S) { + s.RegisterPlugin(junit.NewPlugin()) + s.AddSuite(&applySuite{}) + s.AddSuite(&createSuite{}) + s.AddSuite(&deleteSuite{})