From 9eab6c398251bca29c0e90a6e60eef8be4563d06 Mon Sep 17 00:00:00 2001 From: Marlon Gamez Date: Wed, 20 Jan 2021 14:43:46 -0800 Subject: [PATCH] Add transparent init (#5186) * plumb io.Writer down into runContext() * implement transparent init * handle user not continuing and apply defaults to generated config * add flags to hide functionality and skip confirmation * update flag names, add test for helper function --- cmd/skaffold/app/cmd/build.go | 2 +- cmd/skaffold/app/cmd/build_test.go | 12 +-- cmd/skaffold/app/cmd/debug_test.go | 2 +- cmd/skaffold/app/cmd/delete.go | 2 +- cmd/skaffold/app/cmd/deploy.go | 2 +- cmd/skaffold/app/cmd/dev.go | 2 +- cmd/skaffold/app/cmd/dev_test.go | 4 +- cmd/skaffold/app/cmd/diagnose.go | 2 +- cmd/skaffold/app/cmd/filter.go | 2 +- cmd/skaffold/app/cmd/flags.go | 18 ++++ cmd/skaffold/app/cmd/generate_pipeline.go | 2 +- cmd/skaffold/app/cmd/render.go | 2 +- cmd/skaffold/app/cmd/run.go | 2 +- cmd/skaffold/app/cmd/run_test.go | 2 +- cmd/skaffold/app/cmd/runner.go | 93 ++++++++++++------- cmd/skaffold/app/cmd/runner_test.go | 3 +- cmd/skaffold/app/cmd/test.go | 2 +- docs/content/en/docs/references/cli/_index.md | 12 +++ pkg/skaffold/config/options.go | 2 + pkg/skaffold/initializer/transparent.go | 19 +++- pkg/skaffold/initializer/transparent_test.go | 29 ++++++ 21 files changed, 161 insertions(+), 55 deletions(-) diff --git a/cmd/skaffold/app/cmd/build.go b/cmd/skaffold/app/cmd/build.go index 861e770b6d5..d4a5a12262e 100644 --- a/cmd/skaffold/app/cmd/build.go +++ b/cmd/skaffold/app/cmd/build.go @@ -65,7 +65,7 @@ func doBuild(ctx context.Context, out io.Writer) error { buildOut = ioutil.Discard } - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { bRes, err := r.Build(ctx, buildOut, targetArtifacts(opts, configs)) if quietFlag || buildOutputFlag != "" { diff --git a/cmd/skaffold/app/cmd/build_test.go b/cmd/skaffold/app/cmd/build_test.go index f184638c92d..7e212febef7 100644 --- a/cmd/skaffold/app/cmd/build_test.go +++ b/cmd/skaffold/app/cmd/build_test.go @@ -49,7 +49,7 @@ func (r *mockRunner) Stop() error { } func TestTagFlag(t *testing.T) { - mockCreateRunner := func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + mockCreateRunner := func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return &mockRunner{}, []*latest.SkaffoldConfig{{}}, nil } @@ -68,7 +68,7 @@ func TestTagFlag(t *testing.T) { } func TestQuietFlag(t *testing.T) { - mockCreateRunner := func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + mockCreateRunner := func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return &mockRunner{}, []*latest.SkaffoldConfig{{}}, nil } @@ -114,7 +114,7 @@ func TestQuietFlag(t *testing.T) { } func TestFileOutputFlag(t *testing.T) { - mockCreateRunner := func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + mockCreateRunner := func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return &mockRunner{}, []*latest.SkaffoldConfig{{}}, nil } @@ -177,16 +177,16 @@ func TestFileOutputFlag(t *testing.T) { } func TestRunBuild(t *testing.T) { - errRunner := func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + errRunner := func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return nil, nil, errors.New("some error") } - mockCreateRunner := func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + mockCreateRunner := func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return &mockRunner{}, []*latest.SkaffoldConfig{{}}, nil } tests := []struct { description string - mock func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) + mock func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) shouldErr bool }{ { diff --git a/cmd/skaffold/app/cmd/debug_test.go b/cmd/skaffold/app/cmd/debug_test.go index 5530f4bf0be..67b0f92cae1 100644 --- a/cmd/skaffold/app/cmd/debug_test.go +++ b/cmd/skaffold/app/cmd/debug_test.go @@ -48,7 +48,7 @@ func TestNewCmdDebug(t *testing.T) { func TestDebugIndependentFromDev(t *testing.T) { mockRunner := &mockDevRunner{} testutil.Run(t, "DevDebug", func(t *testutil.T) { - t.Override(&createRunner, func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + t.Override(&createRunner, func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return mockRunner, []*latest.SkaffoldConfig{{}}, nil }) t.Override(&opts, config.SkaffoldOptions{}) diff --git a/cmd/skaffold/app/cmd/delete.go b/cmd/skaffold/app/cmd/delete.go index 05f82f8ed98..aa8b9f522dc 100644 --- a/cmd/skaffold/app/cmd/delete.go +++ b/cmd/skaffold/app/cmd/delete.go @@ -35,7 +35,7 @@ func NewCmdDelete() *cobra.Command { } func doDelete(ctx context.Context, out io.Writer) error { - return withRunner(ctx, func(r runner.Runner, _ []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, _ []*latest.SkaffoldConfig) error { return r.Cleanup(ctx, out) }) } diff --git a/cmd/skaffold/app/cmd/deploy.go b/cmd/skaffold/app/cmd/deploy.go index b48eea4af15..b7fd6f7e6f7 100644 --- a/cmd/skaffold/app/cmd/deploy.go +++ b/cmd/skaffold/app/cmd/deploy.go @@ -51,7 +51,7 @@ func NewCmdDeploy() *cobra.Command { } func doDeploy(ctx context.Context, out io.Writer) error { - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { if opts.SkipRender { return r.DeployAndLog(ctx, out, []build.Artifact{}) } diff --git a/cmd/skaffold/app/cmd/dev.go b/cmd/skaffold/app/cmd/dev.go index 09f398df091..4a053c558fa 100644 --- a/cmd/skaffold/app/cmd/dev.go +++ b/cmd/skaffold/app/cmd/dev.go @@ -60,7 +60,7 @@ func runDev(ctx context.Context, out io.Writer) error { case <-ctx.Done(): return nil default: - err := withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + err := withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { var artifacts []*latest.Artifact for _, cfg := range configs { artifacts = append(artifacts, cfg.Build.Artifacts...) diff --git a/cmd/skaffold/app/cmd/dev_test.go b/cmd/skaffold/app/cmd/dev_test.go index 6e603631294..fd7c2601bc6 100644 --- a/cmd/skaffold/app/cmd/dev_test.go +++ b/cmd/skaffold/app/cmd/dev_test.go @@ -95,7 +95,7 @@ func TestDoDev(t *testing.T) { hasDeployed: test.hasDeployed, errDev: context.Canceled, } - t.Override(&createRunner, func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + t.Override(&createRunner, func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return mockRunner, []*latest.SkaffoldConfig{{}}, nil }) t.Override(&opts, config.SkaffoldOptions{ @@ -145,7 +145,7 @@ func TestDevConfigChange(t *testing.T) { testutil.Run(t, "test config change", func(t *testutil.T) { mockRunner := &mockConfigChangeRunner{} - t.Override(&createRunner, func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + t.Override(&createRunner, func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return mockRunner, []*latest.SkaffoldConfig{{}}, nil }) t.Override(&opts, config.SkaffoldOptions{ diff --git a/cmd/skaffold/app/cmd/diagnose.go b/cmd/skaffold/app/cmd/diagnose.go index fbb3f884b18..a2f6a104eec 100644 --- a/cmd/skaffold/app/cmd/diagnose.go +++ b/cmd/skaffold/app/cmd/diagnose.go @@ -46,7 +46,7 @@ func NewCmdDiagnose() *cobra.Command { } func doDiagnose(ctx context.Context, out io.Writer) error { - runCtx, configs, err := runContext(opts) + runCtx, configs, err := runContext(out, opts) if err != nil { return err } diff --git a/cmd/skaffold/app/cmd/filter.go b/cmd/skaffold/app/cmd/filter.go index d73499bdb31..633cf682110 100644 --- a/cmd/skaffold/app/cmd/filter.go +++ b/cmd/skaffold/app/cmd/filter.go @@ -58,7 +58,7 @@ func NewCmdFilter() *cobra.Command { // runFilter loads the Kubernetes manifests from stdin and applies the debug transformations. // Unlike `skaffold debug`, this filtering affects all images and not just the built artifacts. func runFilter(ctx context.Context, out io.Writer, debuggingFilters bool, buildArtifacts []build.Artifact) error { - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { manifestList, err := manifest.Load(os.Stdin) if err != nil { return fmt.Errorf("loading manifests: %w", err) diff --git a/cmd/skaffold/app/cmd/flags.go b/cmd/skaffold/app/cmd/flags.go index 145331a7bec..a1eb983579b 100644 --- a/cmd/skaffold/app/cmd/flags.go +++ b/cmd/skaffold/app/cmd/flags.go @@ -460,6 +460,24 @@ var flagRegistry = []Flag{ FlagAddMethod: "Var", DefinedOn: []string{"test", "deploy"}, }, + { + Name: "auto-create-config", + Usage: "If true, skaffold will try to create a config for the user's run if it doesn't find one", + Value: &opts.AutoCreateConfig, + DefValue: true, + FlagAddMethod: "BoolVar", + DefinedOn: []string{"debug", "dev", "run"}, + IsEnum: true, + }, + { + Name: "assume-yes", + Usage: "If true, skaffold will skip yes/no confirmation from the user and default to yes", + Value: &opts.AssumeYes, + DefValue: false, + FlagAddMethod: "BoolVar", + DefinedOn: []string{"debug", "dev", "run"}, + IsEnum: true, + }, } func methodNameByType(v reflect.Value) string { diff --git a/cmd/skaffold/app/cmd/generate_pipeline.go b/cmd/skaffold/app/cmd/generate_pipeline.go index 259d3718b0d..dcacc138c71 100644 --- a/cmd/skaffold/app/cmd/generate_pipeline.go +++ b/cmd/skaffold/app/cmd/generate_pipeline.go @@ -44,7 +44,7 @@ func NewCmdGeneratePipeline() *cobra.Command { } func doGeneratePipeline(ctx context.Context, out io.Writer) error { - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { if err := r.GeneratePipeline(ctx, out, configs, configFiles, "pipeline.yaml"); err != nil { return fmt.Errorf("generating : %w", err) } diff --git a/cmd/skaffold/app/cmd/render.go b/cmd/skaffold/app/cmd/render.go index d2c884c019b..a7e036d4789 100644 --- a/cmd/skaffold/app/cmd/render.go +++ b/cmd/skaffold/app/cmd/render.go @@ -60,7 +60,7 @@ func doRender(ctx context.Context, out io.Writer) error { buildOut = out } - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { var bRes []build.Artifact if renderFromBuildOutputFile.String() != "" { diff --git a/cmd/skaffold/app/cmd/run.go b/cmd/skaffold/app/cmd/run.go index 1af6a9e142e..15df02717a5 100644 --- a/cmd/skaffold/app/cmd/run.go +++ b/cmd/skaffold/app/cmd/run.go @@ -41,7 +41,7 @@ func NewCmdRun() *cobra.Command { } func doRun(ctx context.Context, out io.Writer) error { - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { bRes, err := r.Build(ctx, out, targetArtifacts(opts, configs)) if err != nil { return fmt.Errorf("failed to build: %w", err) diff --git a/cmd/skaffold/app/cmd/run_test.go b/cmd/skaffold/app/cmd/run_test.go index 249254d667c..f38a08fd1d9 100644 --- a/cmd/skaffold/app/cmd/run_test.go +++ b/cmd/skaffold/app/cmd/run_test.go @@ -69,7 +69,7 @@ func (r *mockRunRunner) DeployAndLog(context.Context, io.Writer, []build.Artifac func TestBuildImageFlag(t *testing.T) { testutil.Run(t, "", func(t *testutil.T) { mockRunner := &mockRunRunner{} - t.Override(&createRunner, func(config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + t.Override(&createRunner, func(io.Writer, config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { return mockRunner, []*latest.SkaffoldConfig{{ Pipeline: latest.Pipeline{ Build: latest.BuildConfig{ diff --git a/cmd/skaffold/app/cmd/runner.go b/cmd/skaffold/app/cmd/runner.go index 00a6774aeb9..eca77841c7c 100644 --- a/cmd/skaffold/app/cmd/runner.go +++ b/cmd/skaffold/app/cmd/runner.go @@ -20,13 +20,17 @@ import ( "context" "errors" "fmt" + "io" "os" "github.com/sirupsen/logrus" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/color" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" sErrors "github.com/GoogleContainerTools/skaffold/pkg/skaffold/errors" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer" + initConfig "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/config" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/instrumentation" kubectx "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes/context" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner" @@ -42,8 +46,8 @@ import ( // For tests var createRunner = createNewRunner -func withRunner(ctx context.Context, action func(runner.Runner, []*latest.SkaffoldConfig) error) error { - runner, config, err := createRunner(opts) +func withRunner(ctx context.Context, out io.Writer, action func(runner.Runner, []*latest.SkaffoldConfig) error) error { + runner, config, err := createRunner(out, opts) sErrors.SetSkaffoldOptions(opts) if err != nil { return err @@ -55,8 +59,8 @@ func withRunner(ctx context.Context, action func(runner.Runner, []*latest.Skaffo } // createNewRunner creates a Runner and returns the SkaffoldConfig associated with it. -func createNewRunner(opts config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { - runCtx, configs, err := runContext(opts) +func createNewRunner(out io.Writer, opts config.SkaffoldOptions) (runner.Runner, []*latest.SkaffoldConfig, error) { + runCtx, configs, err := runContext(out, opts) if err != nil { return nil, nil, err } @@ -71,10 +75,61 @@ func createNewRunner(opts config.SkaffoldOptions) (runner.Runner, []*latest.Skaf return runner, configs, nil } -func runContext(opts config.SkaffoldOptions) (*runcontext.RunContext, []*latest.SkaffoldConfig, error) { +func runContext(out io.Writer, opts config.SkaffoldOptions) (*runcontext.RunContext, []*latest.SkaffoldConfig, error) { + configs, pipelines, err := skaffoldConfig(out, opts) + if err != nil { + return nil, nil, err + } + + // TODO: Should support per-config kubecontext. Right now we constrain all configs to define the same kubecontext. + kubectx.ConfigureKubeConfig(opts.KubeConfig, opts.KubeContext, configs[0].Deploy.KubeContext) + + if err := validation.Process(configs); err != nil { + return nil, nil, fmt.Errorf("invalid skaffold config: %w", err) + } + + runCtx, err := runcontext.GetRunContext(opts, pipelines) + if err != nil { + return nil, nil, fmt.Errorf("getting run context: %w", err) + } + + if err := validation.ProcessWithRunContext(runCtx); err != nil { + return nil, nil, fmt.Errorf("invalid skaffold config: %w", err) + } + + return runCtx, configs, nil +} + +func setDefaultDeployer(configs []util.VersionedConfig) bool { + // set the default deployer only if no deployer is explicitly specified in any config + for _, cfg := range configs { + if cfg.(*latest.SkaffoldConfig).Deploy.DeployType != (latest.DeployType{}) { + return false + } + } + return true +} + +// skaffoldConfig will try to parse the given opts.ConfigurationFile. If not found, it will try to automatically generate a config for the user +func skaffoldConfig(out io.Writer, opts config.SkaffoldOptions) ([]*latest.SkaffoldConfig, []latest.Pipeline, error) { parsed, err := schema.ParseConfigAndUpgrade(opts.ConfigurationFile, latest.Version) if err != nil { if os.IsNotExist(errors.Unwrap(err)) { + if opts.AutoCreateConfig && initializer.ValidCmd(opts) { + color.Default.Fprintf(out, "Skaffold config file %s not found - Trying to create one for you...\n", opts.ConfigurationFile) + config, err := initializer.Transparent(context.Background(), out, initConfig.Config{Opts: opts}) + if err != nil { + return nil, nil, fmt.Errorf("unable to generate skaffold config file automatically - try running `skaffold init`: %w", err) + } + if config == nil { + return nil, nil, fmt.Errorf("unable to generate skaffold config file automatically - try running `skaffold init`: action cancelled by user") + } + + defaults.Set(config, true) + + return []*latest.SkaffoldConfig{config}, []latest.Pipeline{config.Pipeline}, nil + } + return nil, nil, fmt.Errorf("skaffold config file %s not found - check your current working directory, or try running `skaffold init`", opts.ConfigurationFile) } @@ -105,33 +160,7 @@ func runContext(opts config.SkaffoldOptions) (*runcontext.RunContext, []*latest. configs = append(configs, config) } - // TODO: Should support per-config kubecontext. Right now we constrain all configs to define the same kubecontext. - kubectx.ConfigureKubeConfig(opts.KubeConfig, opts.KubeContext, configs[0].Deploy.KubeContext) - - if err := validation.Process(configs); err != nil { - return nil, nil, fmt.Errorf("invalid skaffold config: %w", err) - } - - runCtx, err := runcontext.GetRunContext(opts, pipelines) - if err != nil { - return nil, nil, fmt.Errorf("getting run context: %w", err) - } - - if err := validation.ProcessWithRunContext(runCtx); err != nil { - return nil, nil, fmt.Errorf("invalid skaffold config: %w", err) - } - - return runCtx, configs, nil -} - -func setDefaultDeployer(configs []util.VersionedConfig) bool { - // set the default deployer only if no deployer is explicitly specified in any config - for _, cfg := range configs { - if cfg.(*latest.SkaffoldConfig).Deploy.DeployType != (latest.DeployType{}) { - return false - } - } - return true + return configs, pipelines, nil } func warnIfUpdateIsAvailable() { diff --git a/cmd/skaffold/app/cmd/runner_test.go b/cmd/skaffold/app/cmd/runner_test.go index eea9cc5b8cf..d57394d71f3 100644 --- a/cmd/skaffold/app/cmd/runner_test.go +++ b/cmd/skaffold/app/cmd/runner_test.go @@ -18,6 +18,7 @@ package cmd import ( "fmt" + "io/ioutil" "testing" "github.com/blang/semver" @@ -98,7 +99,7 @@ func TestCreateNewRunner(t *testing.T) { Write("skaffold.yaml", fmt.Sprintf("apiVersion: %s\nkind: Config\n%s", latest.Version, test.config)). Chdir() - _, _, err := createNewRunner(test.options) + _, _, err := createNewRunner(ioutil.Discard, test.options) t.CheckError(test.shouldErr, err) if test.expectedError != "" { diff --git a/cmd/skaffold/app/cmd/test.go b/cmd/skaffold/app/cmd/test.go index 3538c94da85..aa395cf5e41 100644 --- a/cmd/skaffold/app/cmd/test.go +++ b/cmd/skaffold/app/cmd/test.go @@ -39,7 +39,7 @@ func NewCmdTest() *cobra.Command { } func doTest(ctx context.Context, out io.Writer) error { - return withRunner(ctx, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { + return withRunner(ctx, out, func(r runner.Runner, configs []*latest.SkaffoldConfig) error { var artifacts []*latest.Artifact for _, c := range configs { artifacts = append(artifacts, c.Build.Artifacts...) diff --git a/docs/content/en/docs/references/cli/_index.md b/docs/content/en/docs/references/cli/_index.md index a73b4f36089..dd2d15fc3d4 100644 --- a/docs/content/en/docs/references/cli/_index.md +++ b/docs/content/en/docs/references/cli/_index.md @@ -342,6 +342,8 @@ Env vars: Options: + --assume-yes=false: If true, skaffold will skip yes/no confirmation from the user and default to yes + --auto-create-config=true: If true, skaffold will try to create a config for the user's run if it doesn't find one --cache-artifacts=true: Set to false to disable default caching of artifacts --cache-file='': Specify the location of the cache file (default $HOME/.skaffold/cache) --cleanup=true: Delete deployments after dev or debug mode is interrupted @@ -386,6 +388,8 @@ Use "skaffold options" for a list of global command-line options (applies to all ``` Env vars: +* `SKAFFOLD_ASSUME_YES` (same as `--assume-yes`) +* `SKAFFOLD_AUTO_CREATE_CONFIG` (same as `--auto-create-config`) * `SKAFFOLD_CACHE_ARTIFACTS` (same as `--cache-artifacts`) * `SKAFFOLD_CACHE_FILE` (same as `--cache-file`) * `SKAFFOLD_CLEANUP` (same as `--cleanup`) @@ -552,6 +556,8 @@ Run a pipeline in development mode Options: + --assume-yes=false: If true, skaffold will skip yes/no confirmation from the user and default to yes + --auto-create-config=true: If true, skaffold will try to create a config for the user's run if it doesn't find one --cache-artifacts=true: Set to false to disable default caching of artifacts --cache-file='': Specify the location of the cache file (default $HOME/.skaffold/cache) --cleanup=true: Delete deployments after dev or debug mode is interrupted @@ -597,6 +603,8 @@ Use "skaffold options" for a list of global command-line options (applies to all ``` Env vars: +* `SKAFFOLD_ASSUME_YES` (same as `--assume-yes`) +* `SKAFFOLD_AUTO_CREATE_CONFIG` (same as `--auto-create-config`) * `SKAFFOLD_CACHE_ARTIFACTS` (same as `--cache-artifacts`) * `SKAFFOLD_CACHE_FILE` (same as `--cache-file`) * `SKAFFOLD_CLEANUP` (same as `--cleanup`) @@ -817,6 +825,8 @@ Examples: skaffold run -p Options: + --assume-yes=false: If true, skaffold will skip yes/no confirmation from the user and default to yes + --auto-create-config=true: If true, skaffold will try to create a config for the user's run if it doesn't find one -b, --build-image=[]: Only build artifacts with image names that contain the given substring. Default is to build sources for all artifacts --cache-artifacts=true: Set to false to disable default caching of artifacts --cache-file='': Specify the location of the cache file (default $HOME/.skaffold/cache) @@ -861,6 +871,8 @@ Use "skaffold options" for a list of global command-line options (applies to all ``` Env vars: +* `SKAFFOLD_ASSUME_YES` (same as `--assume-yes`) +* `SKAFFOLD_AUTO_CREATE_CONFIG` (same as `--auto-create-config`) * `SKAFFOLD_BUILD_IMAGE` (same as `--build-image`) * `SKAFFOLD_CACHE_ARTIFACTS` (same as `--cache-artifacts`) * `SKAFFOLD_CACHE_FILE` (same as `--cache-file`) diff --git a/pkg/skaffold/config/options.go b/pkg/skaffold/config/options.go index ac13d5e54eb..e604471aac3 100644 --- a/pkg/skaffold/config/options.go +++ b/pkg/skaffold/config/options.go @@ -57,6 +57,8 @@ type SkaffoldOptions struct { AutoSync bool AutoDeploy bool RenderOnly bool + AutoCreateConfig bool + AssumeYes bool RenderOutput string ProfileAutoActivation bool DryRun bool diff --git a/pkg/skaffold/initializer/transparent.go b/pkg/skaffold/initializer/transparent.go index 8ee0be58e43..f8d6811c9fe 100644 --- a/pkg/skaffold/initializer/transparent.go +++ b/pkg/skaffold/initializer/transparent.go @@ -20,6 +20,7 @@ import ( "context" "io" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" initConfig "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/config" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/initializer/prompt" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" @@ -54,8 +55,10 @@ func Transparent(ctx context.Context, out io.Writer, c initConfig.Config) (*late } // Prompt the user with information about what will happen if they continue with this config. - if done, err := confirmInitOptions(out, newConfig); done { - return nil, err + if !c.Opts.AssumeYes { + if done, err := confirmInitOptions(out, newConfig); done { + return nil, err + } } if err := WriteData(out, c, newConfig, newManifests); err != nil { @@ -64,3 +67,15 @@ func Transparent(ctx context.Context, out io.Writer, c initConfig.Config) (*late return newConfig, nil } + +// Returns true if transparent init should run on the given opts.Command, false otherwise +func ValidCmd(opts config.SkaffoldOptions) bool { + valid := map[string]struct{}{ + "debug": {}, + "dev": {}, + "run": {}, + } + _, ok := valid[opts.Command] + + return ok +} diff --git a/pkg/skaffold/initializer/transparent_test.go b/pkg/skaffold/initializer/transparent_test.go index f1d63d494c5..7542d47f727 100644 --- a/pkg/skaffold/initializer/transparent_test.go +++ b/pkg/skaffold/initializer/transparent_test.go @@ -178,3 +178,32 @@ See https://skaffold.dev/docs/pipeline-stages/deployers/helm/ for a detailed gui }) } } + +func TestValidCmd(t *testing.T) { + tests := []struct { + name string + cmd string + expected bool + }{ + { + name: "valid string", + cmd: "dev", + expected: true, + }, + { + name: "invalid", + cmd: "build", + expected: false, + }, + } + for _, test := range tests { + testutil.Run(t, test.name, func(t *testutil.T) { + config := config.SkaffoldOptions{ + Command: test.cmd, + } + valid := ValidCmd(config) + + t.CheckDeepEqual(test.expected, valid) + }) + } +}