From fa724fe12dad6f0cedff675edc91194a778cd229 Mon Sep 17 00:00:00 2001 From: Ratnadeep Debnath Date: Fri, 4 Nov 2016 00:33:04 +0530 Subject: [PATCH] Allow specifying repo,branch info for buildconfig over CLI. --- cli/command/command.go | 276 +++++++++++++++++++++++++ cmd/convert.go | 10 +- pkg/kobject/kobject.go | 2 + pkg/transformer/openshift/openshift.go | 13 +- 4 files changed, 296 insertions(+), 5 deletions(-) create mode 100644 cli/command/command.go diff --git a/cli/command/command.go b/cli/command/command.go new file mode 100644 index 00000000..654a0739 --- /dev/null +++ b/cli/command/command.go @@ -0,0 +1,276 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package command + +import ( + "fmt" + "strings" + + "github.com/Sirupsen/logrus" + "github.com/kubernetes-incubator/kompose/cli/app" + "github.com/urfave/cli" +) + +// Hook for erroring and exit out on warning +type errorOnWarningHook struct{} + +// array consisting of our common conversion flags that will get passed along +// for the autocomplete aspect +var ( + commonConvertFlagsList = []string{"out", "replicas", "yaml", "stdout", "emptyvols"} +) + +func (errorOnWarningHook) Levels() []logrus.Level { + return []logrus.Level{logrus.WarnLevel} +} + +func (errorOnWarningHook) Fire(entry *logrus.Entry) error { + logrus.Fatalln(entry.Message) + return nil +} + +// BeforeApp is an action that is executed before any cli command. +func BeforeApp(c *cli.Context) error { + + if c.GlobalBool("verbose") { + logrus.SetLevel(logrus.DebugLevel) + } else if c.GlobalBool("suppress-warnings") { + logrus.SetLevel(logrus.ErrorLevel) + } else if c.GlobalBool("error-on-warning") { + hook := errorOnWarningHook{} + logrus.AddHook(hook) + } + + // First command added was dummy convert command so removing it + c.App.Commands = c.App.Commands[1:] + provider := strings.ToLower(c.GlobalString("provider")) + switch provider { + case "kubernetes": + c.App.Commands = append(c.App.Commands, ConvertKubernetesCommand()) + case "openshift": + c.App.Commands = append(c.App.Commands, ConvertOpenShiftCommand()) + default: + logrus.Fatalf("Unknown provider. Supported providers are kubernetes and openshift.") + } + + return nil +} + +// When user tries out `kompose -h`, the convert option should be visible +// so adding a dummy `convert` command, real convert commands depending on Providers +// mentioned are added in `BeforeApp` function +func ConvertCommandDummy() cli.Command { + command := cli.Command{ + Name: "convert", + Usage: fmt.Sprintf("Convert Docker Compose file (e.g. %s) to Kubernetes/OpenShift objects", app.DefaultComposeFile), + } + return command +} + +// Generate the Bash completion flag taking the common flags plus whatever is +// passed into the function to correspond to the primary command specific args +func generateBashCompletion(args []string) { + commonArgs := []string{"bundle", "file", "suppress-warnings", "verbose", "error-on-warning", "provider"} + flags := append(commonArgs, args...) + + for _, f := range flags { + fmt.Printf("--%s\n", f) + } +} + +// ConvertKubernetesCommand defines the kompose convert subcommand for Kubernetes provider +func ConvertKubernetesCommand() cli.Command { + command := cli.Command{ + Name: "convert", + Usage: fmt.Sprintf("Convert Docker Compose file (e.g. %s) to Kubernetes objects", app.DefaultComposeFile), + Action: func(c *cli.Context) { + app.Convert(c) + }, + BashComplete: func(c *cli.Context) { + flags := []string{"chart", "deployment", "daemonset", "replicationcontroller"} + generateBashCompletion(append(flags, commonConvertFlagsList...)) + }, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "chart,c", + Usage: "Create a Helm chart for converted objects", + }, + cli.BoolFlag{ + Name: "deployment,d", + Usage: "Generate a Kubernetes deployment object (default on)", + }, + cli.BoolFlag{ + Name: "daemonset,ds", + Usage: "Generate a Kubernetes daemonset object", + }, + cli.BoolFlag{ + Name: "replicationcontroller,rc", + Usage: "Generate a Kubernetes replication controller object", + }, + }, + } + command.Flags = append(command.Flags, commonConvertFlags()...) + return command +} + +// ConvertOpenShiftCommand defines the kompose convert subcommand for OpenShift provider +func ConvertOpenShiftCommand() cli.Command { + command := cli.Command{ + Name: "convert", + Usage: fmt.Sprintf("Convert Docker Compose file (e.g. %s) to OpenShift objects", app.DefaultComposeFile), + Action: func(c *cli.Context) { + app.Convert(c) + }, + BashComplete: func(c *cli.Context) { + flags := []string{"deploymentconfig"} + generateBashCompletion(append(flags, commonConvertFlagsList...)) + }, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "deploymentconfig,dc", + Usage: "Generate a OpenShift DeploymentConfig object", + }, + cli.BoolFlag{ + Name: "buildconfig,bc", + Usage: "Generate a BuildConfig for Openshift", + }, + cli.StringFlag{ + Name: "repo", + Value: "", + Usage: "Specify source repository for buildconfig (default remote origin)", + EnvVar: "REPO", + }, + cli.StringFlag{ + Name: "branch", + Value: "master", + Usage: "Specify repository branch to use for buildconfig (default master)", + EnvVar: "BRANCH", + }, + }, + } + command.Flags = append(command.Flags, commonConvertFlags()...) + return command +} + +func commonConvertFlags() []cli.Flag { + return []cli.Flag{ + cli.StringFlag{ + Name: "out,o", + Usage: "Specify path to a file or a directory to save generated objects into. If path is a directory, the objects are stored in that directory. If path is a file, then objects are stored in that single file. File is created if it does not exist.", + EnvVar: "OUTPUT_FILE", + }, + cli.IntFlag{ + Name: "replicas", + Value: 1, + Usage: "Specify the number of replicas in the generated resource spec (default 1)", + }, + cli.BoolFlag{ + Name: "yaml, y", + Usage: "Generate resource file in yaml format", + }, + cli.BoolFlag{ + Name: "stdout", + Usage: "Print converted objects to stdout", + }, + cli.BoolFlag{ + Name: "emptyvols", + Usage: "Use Empty Volumes. Don't generate PVCs", + }, + } +} + +// UpCommand defines the kompose up subcommand. +func UpCommand() cli.Command { + return cli.Command{ + Name: "up", + Usage: "Deploy your Dockerized application to Kubernetes (default: creating Kubernetes deployment and service)", + Action: func(c *cli.Context) { + app.Up(c) + }, + BashComplete: func(c *cli.Context) { + flags := []string{"emptyvols"} + generateBashCompletion(flags) + }, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "emptyvols", + Usage: "Use Empty Volumes. Don't generate PVCs", + }, + }, + } +} + +// 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) + }, + BashComplete: func(c *cli.Context) { + flags := []string{"emptyvols"} + generateBashCompletion(flags) + }, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "emptyvols", + Usage: "Use Empty Volumes. Don't generate PVCs", + }, + }, + } +} + +// CommonFlags defines the flags that are in common for all subcommands. +func CommonFlags() []cli.Flag { + return []cli.Flag{ + cli.StringFlag{ + Name: "bundle,dab", + Usage: "Specify a Distributed Application Bundle (DAB) file", + EnvVar: "DAB_FILE", + }, + + cli.StringFlag{ + Name: "file,f", + Usage: fmt.Sprintf("Specify an alternative compose file (default: %s)", app.DefaultComposeFile), + Value: app.DefaultComposeFile, + EnvVar: "COMPOSE_FILE", + }, + // creating a flag to suppress warnings + cli.BoolFlag{ + Name: "suppress-warnings", + Usage: "Suppress all warnings", + }, + // creating a flag to show all kinds of warnings + cli.BoolFlag{ + Name: "verbose", + Usage: "Show all type of logs", + }, + // flag to treat any warning as error + cli.BoolFlag{ + Name: "error-on-warning", + Usage: "Treat any warning as error", + }, + // mention the end provider + cli.StringFlag{ + Name: "provider", + Usage: "Generate artifacts for this provider", + Value: app.DefaultProvider, + EnvVar: "PROVIDER", + }, + } +} diff --git a/cmd/convert.go b/cmd/convert.go index f7c23d63..a3539f42 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -26,7 +26,7 @@ import ( ) var ( - ConvertSource, ConvertOut string + ConvertSource, ConvertOut, ConvertRepo, ConvertBranch string ConvertChart, ConvertDeployment, ConvertDaemonSet bool ConvertReplicationController, ConvertYaml, ConvertStdout bool ConvertEmptyVols, ConvertDeploymentConfig, ConvertBuildConfig bool @@ -54,6 +54,8 @@ var convertCmd = &cobra.Command{ CreateDS: ConvertDaemonSet, CreateRC: ConvertReplicationController, CreateBuildConfig: ConvertBuildConfig, + Repo: ConvertRepo, + Branch: ConvertBranch, CreateDeploymentConfig: ConvertDeploymentConfig, EmptyVols: ConvertEmptyVols, } @@ -87,6 +89,10 @@ func init() { convertCmd.Flags().MarkHidden("deployment-config") convertCmd.Flags().BoolVar(&ConvertBuildConfig, "build-config", false, "Generate an OpenShift buildconfig object") convertCmd.Flags().MarkHidden("build-config") + convertCmd.Flags().StringVar(&ConvertRepo, "repo", "", "Specify source repository for buildconfig (default remote origin)") + convertCmd.Flags().MarkHidden("repo") + convertCmd.Flags().StringVar(&ConvertBranch, "branch", "master", "Specify repository branch to use for buildconfig (default master)") + convertCmd.Flags().MarkHidden("branch") // Standard between the two convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into yaml format") @@ -110,12 +116,14 @@ Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}} Resource Flags: + --branch Specify repository branch to use for buildconfig (default master) --build-config Generate an Openshift build config object -c, --chart Create a Helm chart for converted objects --daemon-set Generate a Kubernetes daemonset object -d, --deployment Generate a Kubernetes deployment object --deployment-config Generate an OpenShift deployment config object --replication-controller Generate a Kubernetes replication controller object + --repo Specify source repository for buildconfig (default remote origin) Flags: {{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}} diff --git a/pkg/kobject/kobject.go b/pkg/kobject/kobject.go index e5715e37..af2eb480 100644 --- a/pkg/kobject/kobject.go +++ b/pkg/kobject/kobject.go @@ -34,6 +34,8 @@ type ConvertOptions struct { CreateDS bool CreateDeploymentConfig bool CreateBuildConfig bool + Repo string + Branch string CreateChart bool GenerateYaml bool EmptyVols bool diff --git a/pkg/transformer/openshift/openshift.go b/pkg/transformer/openshift/openshift.go index 10ff71ee..47df58c7 100644 --- a/pkg/transformer/openshift/openshift.go +++ b/pkg/transformer/openshift/openshift.go @@ -146,7 +146,12 @@ func (o *OpenShift) initImageStream(name string, service kobject.ServiceConfig) } // initBuildConfig initialize Openshifts BuildConfig Object -func initBuildConfig(name string, service kobject.ServiceConfig, inputFile string) *buildapi.BuildConfig { +func initBuildConfig(name string, service kobject.ServiceConfig, inputFile string, repo string, branch string) *buildapi.BuildConfig { + uri := repo + if uri == "" { + uri = getGitRemote("origin") + } + bc := &buildapi.BuildConfig{ TypeMeta: unversioned.TypeMeta{ Kind: "BuildConfig", @@ -166,8 +171,8 @@ func initBuildConfig(name string, service kobject.ServiceConfig, inputFile strin buildapi.CommonSpec{ Source: buildapi.BuildSource{ Git: &buildapi.GitBuildSource{ - Ref: "master", - URI: getGitRemote("origin"), + Ref: branch, + URI: uri, }, ContextDir: getAbsBuildContext(service.Build, inputFile), }, @@ -301,7 +306,7 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C } if opt.CreateBuildConfig && service.Build != "" { - objects = append(objects, initBuildConfig(name, service, opt.InputFile)) // Openshift BuildConfigs + objects = append(objects, initBuildConfig(name, service, opt.InputFile, opt.Repo, opt.Branch)) // Openshift BuildConfigs } // If ports not provided in configuration we will not make service