diff --git a/cmd/init.go b/cmd/init.go index 4a7ef31ebf2c4a5a35eb6a1f847f47c30ab7c316..3320522c6636ba88914ba30c653d51708a9c6182 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -16,9 +16,10 @@ package cmd import ( + "errors" "fmt" "os" - "path" + "path/filepath" "github.com/ksonnet/ksonnet/metadata" "github.com/ksonnet/ksonnet/pkg/kubecfg" @@ -26,6 +27,10 @@ import ( "github.com/spf13/cobra" ) +const ( + flagInitDir = "dir" +) + func init() { RootCmd.AddCommand(initCmd) // TODO: We need to make this default to checking the `kubeconfig` file. @@ -33,6 +38,7 @@ func init() { "Manually specify API version from OpenAPI schema, cluster, or Kubernetes version") bindClientGoFlags(initCmd) + initCmd.Flags().String(flagInitDir, "", "Ksonnet application directory") } var initCmd = &cobra.Command{ @@ -45,11 +51,22 @@ var initCmd = &cobra.Command{ } appName := args[0] - appDir, err := os.Getwd() + wd, err := os.Getwd() + if err != nil { + return err + } + + initDir, err := flags.GetString(flagInitDir) + if err != nil { + return err + } + + path, err := genKsRoot(appName, wd, initDir) if err != nil { return err } - appRoot := metadata.AbsPath(path.Join(appDir, appName)) + + appRoot := metadata.AbsPath(path) specFlag, err := flags.GetString(flagAPISpec) if err != nil { @@ -120,5 +137,29 @@ ks init app-name --api-spec=version:v1.7.1 # Initialize a ksonnet application, using the OpenAPI spec generated by a # specific build of Kubernetes to generate 'ksonnet-lib'. -ks init app-name --api-spec=file:swagger.json`, +ks init app-name --api-spec=file:swagger.json + +# Initialize a ksonnet application, using a custom location for the application +# directory. +ks init app-name --dir=custom-location`, +} + +func genKsRoot(appName, ksDir, wd string) (string, error) { + if ksDir == "" { + return "", errors.New("invalid working directory") + } + + if appName == "" && wd == "" { + return "", errors.New("invalid application name") + } + + if wd != "" { + if filepath.IsAbs(wd) { + return wd, nil + } + + return filepath.Abs(filepath.Join(ksDir, wd)) + } + + return filepath.Join(ksDir, appName), nil } diff --git a/cmd/init_test.go b/cmd/init_test.go new file mode 100644 index 0000000000000000000000000000000000000000..228e6b69672c9aefa25e5bb7d23da50db0a8ae8e --- /dev/null +++ b/cmd/init_test.go @@ -0,0 +1,37 @@ +package cmd + +import "testing" + +func Test_genKsRoot(t *testing.T) { + cases := []struct { + name string + appName string + ksDir string + wd string + expected string + isErr bool + }{ + {name: "no wd", appName: "app", ksDir: "/root", expected: "/root/app"}, + {name: "with abs wd", appName: "app", ksDir: "/root", wd: "/custom", expected: "/custom"}, + {name: "with rel wd #1", appName: "app", ksDir: "/root", wd: "./custom", expected: "/root/custom"}, + {name: "with rel wd #2", appName: "app", ksDir: "/root", wd: "custom", expected: "/root/custom"}, + {name: "with rel wd #2", appName: "app", ksDir: "/root", wd: "../custom", expected: "/custom"}, + {name: "missing ksDir", appName: "app", wd: "./custom", isErr: true}, + {name: "missing appName and wd", ksDir: "/root", isErr: true}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := genKsRoot(tc.appName, tc.ksDir, tc.wd) + if tc.isErr { + if err == nil { + t.Errorf("genKsRoot expected error, but none was received") + } + } else { + if got != tc.expected { + t.Errorf("genKsRoot got %q; expected %q", got, tc.expected) + } + } + }) + } +} diff --git a/docs/cli-reference/ks_init.md b/docs/cli-reference/ks_init.md index 9be0796d5838b89aed7434c12c9f6e500344ae9d..3f1a2597b6f7e9404dc8fdc72ba947300c354a81 100644 --- a/docs/cli-reference/ks_init.md +++ b/docs/cli-reference/ks_init.md @@ -36,7 +36,7 @@ of the current context specified in `$KUBECONFIG`. ``` -ks init <app-name> +ks init <app-name> [flags] ``` ### Examples @@ -65,6 +65,10 @@ ks init app-name --api-spec=version:v1.7.1 # Initialize a ksonnet application, using the OpenAPI spec generated by a # specific build of Kubernetes to generate 'ksonnet-lib'. ks init app-name --api-spec=file:swagger.json + +# Initialize a ksonnet application, using a custom location for the application +# directory. +ks init app-name --dir=custom-location ``` ### Options @@ -77,6 +81,7 @@ ks init app-name --api-spec=file:swagger.json --client-key string Path to a client key file for TLS --cluster string The name of the kubeconfig cluster to use --context string The name of the kubeconfig context to use + --dir string Ksonnet application directory --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure --kubeconfig string Path to a kube config. Only required if out-of-cluster -n, --namespace string If present, the namespace scope for this CLI request