diff --git a/cli/app/app.go b/cli/app/app.go index e1221ce7..a6426f26 100644 --- a/cli/app/app.go +++ b/cli/app/app.go @@ -213,6 +213,49 @@ 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) + + // 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 +273,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..88b497e1 100644 --- a/cli/command/command.go +++ b/cli/command/command.go @@ -109,72 +109,29 @@ 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", + }, + }, + } +} // 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..d8e2abda 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 { @@ -294,3 +297,31 @@ 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) { + //delete svc + rpService, err := kubectl.ReaperFor(api.Kind("Service"), client) + if err != nil { + 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.Warningf("Can't delete service: %s due to '%v'", name, err) + } else { + logrus.Infof("Successfully deleted service: %s", name) + } + + //delete deployment + rpDeployment, err := kubectl.ReaperFor(extensions.Kind("Deployment"), client) + if err != nil { + 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.Warningf("Can't delete deployment: %s due to '%v'", name, err) + } else { + logrus.Infof("Successfully deleted deployment: %s", name) + } +}