From e08ab06f2c1dacf2bae477bb5faace2feb387c90 Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 17 Aug 2016 14:21:51 +0700 Subject: [PATCH 1/3] support kompose down --- cli/app/app.go | 72 ++++++++++++++++++ cli/command/command.go | 94 +++++++----------------- cli/main/main.go | 2 +- pkg/transformer/kubernetes/kubernetes.go | 72 ++++++++++++++++++ 4 files changed, 173 insertions(+), 67 deletions(-) diff --git a/cli/app/app.go b/cli/app/app.go index e1221ce7..cd30bf3a 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -213,6 +213,62 @@ func Up(c *cli.Context) { kubernetes.CreateObjects(client, objects) } +// Down deletes all deployment, svc. +func Down(c *cli.Context) { + factory := cmdutil.NewFactory(nil) + clientConfig, err := factory.ClientConfig() + if err != nil { + logrus.Fatalf("Failed to access the Kubernetes cluster. Make sure you have a Kubernetes running: %v", err) + } + client := client.NewOrDie(clientConfig) + + inputFile := c.String("file") + dabFile := c.String("bundle") + + komposeObject := kobject.KomposeObject{ + ServiceConfigs: make(map[string]kobject.ServiceConfig), + } + + file := inputFile + if len(dabFile) > 0 { + inputFormat = "bundle" + file = dabFile + } + + opt := kobject.ConvertOptions{} + + validateFlags(opt, false, dabFile, inputFile) + + if c.BoolT("all") { + if len(file) > 0 && file != "docker-compose.yml" { + logrus.Fatalf("Error: --file/--bundle and --all cannot be specified at the same time") + } + fmt.Println("Using flag --all/-a will delete all resources in the kubernetes cluster.") + fmt.Print("Are you sure to continue? (yes/no): ") + if !askForConfirmation() { + return + } + kubernetes.DeleteAll(client) + return + } + + // loader parses input from file into komposeObject. + var l loader.Loader + switch inputFormat { + case "bundle": + l = new(bundle.Bundle) + case "compose": + l = new(compose.Compose) + default: + logrus.Fatalf("Input file format is not supported") + } + komposeObject = l.LoadFile(file) + + for k := range komposeObject.ServiceConfigs { + kubernetes.DeleteObjects(client, k) + } +} + // the objects that we get can be in any order this keeps services first // according to best practice kubernetes services should be created first // http://kubernetes.io/docs/user-guide/config-best-practices/ @@ -230,3 +286,19 @@ func sortServicesFirst(objs *[]runtime.Object) { ret = append(ret, others...) *objs = ret } + +func askForConfirmation() bool { + var response string + _, err := fmt.Scanln(&response) + if err != nil { + logrus.Fatal(err) + } + if response == "yes" { + return true + } else if response == "no" { + return false + } else { + fmt.Println("Please type yes or no and then press enter:") + return askForConfirmation() + } +} diff --git a/cli/command/command.go b/cli/command/command.go index 52e7387d..594a68fc 100644 --- a/cli/command/command.go +++ b/cli/command/command.go @@ -109,72 +109,34 @@ func UpCommand() cli.Command { } } -// PsCommand defines the kompose ps subcommand. -//func PsCommand() cli.Command { -// return cli.Command{ -// Name: "ps", -// Usage: "Get active data in the kubernetes cluster", -// Action: func(c *cli.Context) { -// app.Ps(c) -// }, -// Flags: []cli.Flag{ -// cli.BoolFlag{ -// Name: "service,svc", -// Usage: "Get active services", -// }, -// cli.BoolFlag{ -// Name: "replicationcontroller,rc", -// Usage: "Get active replication controller", -// }, -// }, -// } -//} - -// DeleteCommand defines the kompose delete subcommand. -//func DeleteCommand() cli.Command { -// return cli.Command{ -// Name: "delete", -// Usage: "Remove instantiated services/rc from kubernetes", -// Action: func(c *cli.Context) { -// app.Delete(c) -// }, -// Flags: []cli.Flag{ -// cli.BoolFlag{ -// Name: "replicationcontroller,rc", -// Usage: "Remove active replication controllers", -// }, -// cli.BoolFlag{ -// Name: "service,svc", -// Usage: "Remove active services", -// }, -// cli.StringFlag{ -// Name: "name", -// Usage: "Name of the object to remove", -// }, -// }, -// } -//} - -// ScaleCommand defines the kompose up subcommand. -//func ScaleCommand() cli.Command { -// return cli.Command{ -// Name: "scale", -// Usage: "Globally scale instantiated replication controllers", -// Action: func(c *cli.Context) { -// app.Scale(c) -// }, -// Flags: []cli.Flag{ -// cli.IntFlag{ -// Name: "scale", -// Usage: "New number of replicas", -// }, -// cli.StringFlag{ -// Name: "replicationcontroller,rc", -// Usage: "A specific replication controller to scale", -// }, -// }, -// } -//} +// DownCommand defines the kompose down subcommand. +func DownCommand() cli.Command { + return cli.Command{ + Name: "down", + Usage: "Delete instantiated services/deployments from kubernetes", + Action: func(c *cli.Context) { + app.Down(c) + }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "file,f", + Usage: fmt.Sprintf("Specify an alternative compose file (default: %s)", app.DefaultComposeFile), + Value: app.DefaultComposeFile, + EnvVar: "COMPOSE_FILE", + }, + cli.StringFlag{ + Name: "bundle,dab", + Usage: "Specify a Distributed Application Bundle (DAB) file", + EnvVar: "DAB_FILE", + }, + cli.BoolFlag{ + Name: "all, a", + Usage: "Delete all resources in default namespace of the kubernetes cluster", + EnvVar: "DOWN_ALL", + }, + }, + } +} // CommonFlags defines the flags that are in common for all subcommands. func CommonFlags() []cli.Flag { diff --git a/cli/main/main.go b/cli/main/main.go index 4d40a7b4..decad4cb 100644 --- a/cli/main/main.go +++ b/cli/main/main.go @@ -38,9 +38,9 @@ func main() { app.Commands = []cli.Command{ command.ConvertCommand(), command.UpCommand(), + command.DownCommand(), // TODO: enable these commands and update docs once we fix them //command.PsCommand(), - //command.DeleteCommand(), //command.ScaleCommand(), } diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index ff96c7ae..94935255 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -294,3 +294,75 @@ func CreateObjects(client *client.Client, objects []runtime.Object) { } fmt.Println("\nYour application has been deployed to Kubernetes. You can run 'kubectl get deployment,svc,pods' for details.") } + +func DeleteObjects(client *client.Client, name string) { + err := client.Services(api.NamespaceDefault).Delete(name) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting service: %s", err, name) + } + logrus.Infof("Successfully deleted service: %s", name) + + err = client.Deployments(api.NamespaceDefault).Delete(name, nil) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, name) + } + logrus.Infof("Successfully deleted deployment: %s", name) +} + +func DeleteAll(client *client.Client) { + //delete all svc + listOpts := api.ListOptions{} + svcs, err := client.Services(api.NamespaceDefault).List(listOpts) + if err != nil { + logrus.Fatalf("Error: '%v' while listing services in the cluster", err) + } + for _, svc := range svcs.Items { + if svc.Name == "kubernetes" { + continue + } + err = client.Services(api.NamespaceDefault).Delete(svc.Name) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting service: %s", err, svc.Name) + } + logrus.Infof("Successfully deleted service: %s", svc.Name) + } + + //delete all deployment + deployments, err := client.Deployments(api.NamespaceDefault).List(listOpts) + if err != nil { + logrus.Fatalf("Error: '%v' while listing deployments in the cluster", err) + } + for _, deployment := range deployments.Items { + err = client.Deployments(api.NamespaceDefault).Delete(deployment.Name, nil) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, deployment.Name) + } + logrus.Infof("Successfully deleted deployment: %s", deployment.Name) + } + + //delete all daemonset + daemons, err := client.DaemonSets(api.NamespaceDefault).List(listOpts) + if err != nil { + logrus.Fatalf("Error: '%v' while listing daemonsets in the cluster", err) + } + for _, daemon := range daemons.Items { + err = client.DaemonSets(api.NamespaceDefault).Delete(daemon.Name) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting daemonset: %s", err, daemon.Name) + } + logrus.Infof("Successfully deleted daemonset: %s", daemon.Name) + } + + //delete all rc + rcs, err := client.ReplicationControllers(api.NamespaceDefault).List(listOpts) + if err != nil { + logrus.Fatalf("Error: '%v' while listing replication controllers in the cluster", err) + } + for _, rc := range rcs.Items { + err = client.ReplicationControllers(api.NamespaceDefault).Delete(rc.Name) + if err != nil { + logrus.Fatalf("Error: '%v' while deleting replication controller: %s", err, rc.Name) + } + logrus.Infof("Successfully deleted replication controller: %s", rc.Name) + } +} From aafba39a4239f28ed4e6d160cc236ce0c070d3e2 Mon Sep 17 00:00:00 2001 From: Tuna Date: Fri, 19 Aug 2016 17:48:44 +0700 Subject: [PATCH 2/3] use reapers to delete objects --- cli/app/app.go | 3 +- pkg/transformer/kubernetes/kubernetes.go | 60 +++++++++++++++--------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/cli/app/app.go b/cli/app/app.go index cd30bf3a..b3eed701 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -243,8 +243,7 @@ func Down(c *cli.Context) { if len(file) > 0 && file != "docker-compose.yml" { logrus.Fatalf("Error: --file/--bundle and --all cannot be specified at the same time") } - fmt.Println("Using flag --all/-a will delete all resources in the kubernetes cluster.") - fmt.Print("Are you sure to continue? (yes/no): ") + fmt.Print("Are you sure? (yes/no): ") if !askForConfirmation() { return } diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 94935255..69009d53 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -31,6 +31,9 @@ import ( client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/intstr" + //"k8s.io/kubernetes/pkg/controller/daemon" + "k8s.io/kubernetes/pkg/kubectl" + "time" ) type Kubernetes struct { @@ -296,13 +299,25 @@ func CreateObjects(client *client.Client, objects []runtime.Object) { } func DeleteObjects(client *client.Client, name string) { - err := client.Services(api.NamespaceDefault).Delete(name) + //delete svc + rpService, err := kubectl.ReaperFor(api.Kind("Service"), client) + if err != nil { + logrus.Fatalf("Error: '%v' while getting reaper for service", err) + } + //FIXME: timeout = 300s, gracePeriod is nil + err = rpService.Stop(api.NamespaceDefault, name, 300*time.Second, nil) if err != nil { logrus.Fatalf("Error: '%v' while deleting service: %s", err, name) } logrus.Infof("Successfully deleted service: %s", name) - err = client.Deployments(api.NamespaceDefault).Delete(name, nil) + //delete deployment + rpDeployment, err := kubectl.ReaperFor(extensions.Kind("Deployment"), client) + if err != nil { + logrus.Fatalf("Error: '%v' while getting reaper for deployment", err) + } + //FIXME: timeout = 300s, gracePeriod is nil + err = rpDeployment.Stop(api.NamespaceDefault, name, 300*time.Second, nil) if err != nil { logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, name) } @@ -311,6 +326,10 @@ func DeleteObjects(client *client.Client, name string) { func DeleteAll(client *client.Client) { //delete all svc + rpService, err := kubectl.ReaperFor(api.Kind("Service"), client) + if err != nil { + logrus.Fatalf("Error: '%v' while getting reaper for service", err) + } listOpts := api.ListOptions{} svcs, err := client.Services(api.NamespaceDefault).List(listOpts) if err != nil { @@ -320,7 +339,7 @@ func DeleteAll(client *client.Client) { if svc.Name == "kubernetes" { continue } - err = client.Services(api.NamespaceDefault).Delete(svc.Name) + err = rpService.Stop(api.NamespaceDefault, svc.Name, 300*time.Second, nil) if err != nil { logrus.Fatalf("Error: '%v' while deleting service: %s", err, svc.Name) } @@ -328,12 +347,17 @@ func DeleteAll(client *client.Client) { } //delete all deployment + rpDeployment, err := kubectl.ReaperFor(extensions.Kind("Deployment"), client) + if err != nil { + logrus.Fatalf("Error: '%v' while getting reaper for deployment", err) + } deployments, err := client.Deployments(api.NamespaceDefault).List(listOpts) if err != nil { logrus.Fatalf("Error: '%v' while listing deployments in the cluster", err) } + //FIXME: timeout = 300s, gracePeriod is nil for _, deployment := range deployments.Items { - err = client.Deployments(api.NamespaceDefault).Delete(deployment.Name, nil) + err = rpDeployment.Stop(api.NamespaceDefault, deployment.Name, 300*time.Second, nil) if err != nil { logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, deployment.Name) } @@ -341,28 +365,22 @@ func DeleteAll(client *client.Client) { } //delete all daemonset - daemons, err := client.DaemonSets(api.NamespaceDefault).List(listOpts) + rpDaemonSet, err := kubectl.ReaperFor(extensions.Kind("DaemonSet"), client) + if err != nil { + logrus.Fatalf("Error: '%v' while getting reaper for daemonset", err) + } + daemonsets, err := client.DaemonSets(api.NamespaceDefault).List(listOpts) if err != nil { logrus.Fatalf("Error: '%v' while listing daemonsets in the cluster", err) } - for _, daemon := range daemons.Items { - err = client.DaemonSets(api.NamespaceDefault).Delete(daemon.Name) + //FIXME: timeout = 300s, gracePeriod is nil + for _, daemonset := range daemonsets.Items { + err = rpDaemonSet.Stop(api.NamespaceDefault, daemonset.Name, 300*time.Second, nil) if err != nil { - logrus.Fatalf("Error: '%v' while deleting daemonset: %s", err, daemon.Name) + logrus.Fatalf("Error: '%v' while deleting daemonset: %s", err, daemonset.Name) } - logrus.Infof("Successfully deleted daemonset: %s", daemon.Name) + logrus.Infof("Successfully deleted daemonset: %s", daemonset.Name) } - //delete all rc - rcs, err := client.ReplicationControllers(api.NamespaceDefault).List(listOpts) - if err != nil { - logrus.Fatalf("Error: '%v' while listing replication controllers in the cluster", err) - } - for _, rc := range rcs.Items { - err = client.ReplicationControllers(api.NamespaceDefault).Delete(rc.Name) - if err != nil { - logrus.Fatalf("Error: '%v' while deleting replication controller: %s", err, rc.Name) - } - logrus.Infof("Successfully deleted replication controller: %s", rc.Name) - } + //TODO: delete all jobs } From f2769066ca5270dac86367854e6ec3c041337992 Mon Sep 17 00:00:00 2001 From: Tuna Date: Fri, 19 Aug 2016 19:43:34 +0700 Subject: [PATCH 3/3] only print warning and keep deleting objects --- cli/app/app.go | 12 ---- cli/command/command.go | 5 -- pkg/transformer/kubernetes/kubernetes.go | 75 +++--------------------- 3 files changed, 8 insertions(+), 84 deletions(-) diff --git a/cli/app/app.go b/cli/app/app.go index b3eed701..a6426f26 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -239,18 +239,6 @@ func Down(c *cli.Context) { validateFlags(opt, false, dabFile, inputFile) - if c.BoolT("all") { - if len(file) > 0 && file != "docker-compose.yml" { - logrus.Fatalf("Error: --file/--bundle and --all cannot be specified at the same time") - } - fmt.Print("Are you sure? (yes/no): ") - if !askForConfirmation() { - return - } - kubernetes.DeleteAll(client) - return - } - // loader parses input from file into komposeObject. var l loader.Loader switch inputFormat { diff --git a/cli/command/command.go b/cli/command/command.go index 594a68fc..88b497e1 100644 --- a/cli/command/command.go +++ b/cli/command/command.go @@ -129,11 +129,6 @@ func DownCommand() cli.Command { Usage: "Specify a Distributed Application Bundle (DAB) file", EnvVar: "DAB_FILE", }, - cli.BoolFlag{ - Name: "all, a", - Usage: "Delete all resources in default namespace of the kubernetes cluster", - EnvVar: "DOWN_ALL", - }, }, } } diff --git a/pkg/transformer/kubernetes/kubernetes.go b/pkg/transformer/kubernetes/kubernetes.go index 69009d53..d8e2abda 100644 --- a/pkg/transformer/kubernetes/kubernetes.go +++ b/pkg/transformer/kubernetes/kubernetes.go @@ -302,85 +302,26 @@ func DeleteObjects(client *client.Client, name string) { //delete svc rpService, err := kubectl.ReaperFor(api.Kind("Service"), client) if err != nil { - logrus.Fatalf("Error: '%v' while getting reaper for service", err) + logrus.Warningf("Can't get reaper for service due to '%v'", err) } //FIXME: timeout = 300s, gracePeriod is nil err = rpService.Stop(api.NamespaceDefault, name, 300*time.Second, nil) if err != nil { - logrus.Fatalf("Error: '%v' while deleting service: %s", err, name) + logrus.Warningf("Can't delete service: %s due to '%v'", name, err) + } else { + logrus.Infof("Successfully deleted service: %s", name) } - logrus.Infof("Successfully deleted service: %s", name) //delete deployment rpDeployment, err := kubectl.ReaperFor(extensions.Kind("Deployment"), client) if err != nil { - logrus.Fatalf("Error: '%v' while getting reaper for deployment", err) + logrus.Warningf("Can't get reaper for deployment due to '%v'", err) } //FIXME: timeout = 300s, gracePeriod is nil err = rpDeployment.Stop(api.NamespaceDefault, name, 300*time.Second, nil) if err != nil { - logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, name) + logrus.Warningf("Can't delete deployment: %s due to '%v'", name, err) + } else { + logrus.Infof("Successfully deleted deployment: %s", name) } - logrus.Infof("Successfully deleted deployment: %s", name) -} - -func DeleteAll(client *client.Client) { - //delete all svc - rpService, err := kubectl.ReaperFor(api.Kind("Service"), client) - if err != nil { - logrus.Fatalf("Error: '%v' while getting reaper for service", err) - } - listOpts := api.ListOptions{} - svcs, err := client.Services(api.NamespaceDefault).List(listOpts) - if err != nil { - logrus.Fatalf("Error: '%v' while listing services in the cluster", err) - } - for _, svc := range svcs.Items { - if svc.Name == "kubernetes" { - continue - } - err = rpService.Stop(api.NamespaceDefault, svc.Name, 300*time.Second, nil) - if err != nil { - logrus.Fatalf("Error: '%v' while deleting service: %s", err, svc.Name) - } - logrus.Infof("Successfully deleted service: %s", svc.Name) - } - - //delete all deployment - rpDeployment, err := kubectl.ReaperFor(extensions.Kind("Deployment"), client) - if err != nil { - logrus.Fatalf("Error: '%v' while getting reaper for deployment", err) - } - deployments, err := client.Deployments(api.NamespaceDefault).List(listOpts) - if err != nil { - logrus.Fatalf("Error: '%v' while listing deployments in the cluster", err) - } - //FIXME: timeout = 300s, gracePeriod is nil - for _, deployment := range deployments.Items { - err = rpDeployment.Stop(api.NamespaceDefault, deployment.Name, 300*time.Second, nil) - if err != nil { - logrus.Fatalf("Error: '%v' while deleting deployment: %s", err, deployment.Name) - } - logrus.Infof("Successfully deleted deployment: %s", deployment.Name) - } - - //delete all daemonset - rpDaemonSet, err := kubectl.ReaperFor(extensions.Kind("DaemonSet"), client) - if err != nil { - logrus.Fatalf("Error: '%v' while getting reaper for daemonset", err) - } - daemonsets, err := client.DaemonSets(api.NamespaceDefault).List(listOpts) - if err != nil { - logrus.Fatalf("Error: '%v' while listing daemonsets in the cluster", err) - } - //FIXME: timeout = 300s, gracePeriod is nil - for _, daemonset := range daemonsets.Items { - err = rpDaemonSet.Stop(api.NamespaceDefault, daemonset.Name, 300*time.Second, nil) - if err != nil { - logrus.Fatalf("Error: '%v' while deleting daemonset: %s", err, daemonset.Name) - } - logrus.Infof("Successfully deleted daemonset: %s", daemonset.Name) - } - - //TODO: delete all jobs }