From bdefc0bf3b024b522fab705faf1a8ef1a6538498 Mon Sep 17 00:00:00 2001
From: Angus Lees <gus@inodes.org>
Date: Fri, 9 Jun 2017 12:29:55 +1000
Subject: [PATCH] Implement delete subcommand

This removes all objects listed in config files (and dependents) -
effectively reversing an `update --create`.

Intended for short-lived "try this out; now clean up" workflows.

Fixes #14
---
 cmd/delete.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
 utils/sort.go |  5 ++++
 2 files changed, 78 insertions(+)
 create mode 100644 cmd/delete.go

diff --git a/cmd/delete.go b/cmd/delete.go
new file mode 100644
index 00000000..2975cfb2
--- /dev/null
+++ b/cmd/delete.go
@@ -0,0 +1,73 @@
+package cmd
+
+import (
+	"fmt"
+
+	"github.com/golang/glog"
+	"github.com/spf13/cobra"
+	"k8s.io/client-go/pkg/api/errors"
+	"k8s.io/client-go/pkg/api/v1"
+
+	"github.com/ksonnet/kubecfg/utils"
+)
+
+const (
+	flagGracePeriod = "grace-period"
+)
+
+func init() {
+	RootCmd.AddCommand(deleteCmd)
+	deleteCmd.PersistentFlags().Int64(flagGracePeriod, -1, "Number of seconds given to resources to terminate gracefully. A negative value is ignored")
+}
+
+var deleteCmd = &cobra.Command{
+	Use:   "delete",
+	Short: "Delete Kubernetes resources described in local config",
+	RunE: func(cmd *cobra.Command, args []string) error {
+		flags := cmd.Flags()
+		boolFalse := false
+
+		gracePeriod, err := flags.GetInt64(flagGracePeriod)
+		if err != nil {
+			return err
+		}
+
+		objs, err := readObjs(cmd, args)
+		if err != nil {
+			return err
+		}
+
+		clientpool, disco, err := restClientPool(cmd)
+		if err != nil {
+			return err
+		}
+
+		defaultNs, _, err := clientConfig.Namespace()
+
+		utils.SortDepLast(objs)
+
+		deleteOpts := v1.DeleteOptions{OrphanDependents: &boolFalse}
+		if gracePeriod >= 0 {
+			deleteOpts.GracePeriodSeconds = &gracePeriod
+		}
+
+		for _, obj := range objs {
+			desc := fmt.Sprintf("%s/%s", obj.GetKind(), fqName(obj))
+			glog.Info("Deleting ", desc)
+
+			c, err := clientForResource(clientpool, disco, obj, defaultNs)
+			if err != nil {
+				return err
+			}
+
+			err = c.Delete(obj.GetName(), &deleteOpts)
+			if err != nil && !errors.IsNotFound(err) {
+				return fmt.Errorf("Error deleting %s: %s", desc, err)
+			}
+
+			glog.V(2).Info("Deleted object: ", obj)
+		}
+
+		return nil
+	},
+}
diff --git a/utils/sort.go b/utils/sort.go
index 554f4c24..3f92be07 100644
--- a/utils/sort.go
+++ b/utils/sort.go
@@ -57,3 +57,8 @@ func (l dependentObjects) Less(i, j int) bool {
 func SortDepFirst(objs []*runtime.Unstructured) {
 	sort.Sort(dependentObjects(objs))
 }
+
+// SortDepLast is the reverse order of SortDepFirst.
+func SortDepLast(objs []*runtime.Unstructured) {
+	sort.Sort(sort.Reverse(dependentObjects(objs)))
+}
-- 
GitLab