From 925db59377d0c8107f738dc4cc94ba8e7870d419 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 30 Aug 2025 00:44:43 +0200 Subject: [PATCH] cli/command/context: deprecate exported types and functions These functions and types are shallow wrappers around the context store and were intended for internal use as implementation for the CLI itself. They were exported in 3126920af14ea5127e00a2f8f9d8e07a6c3f6ff9 to be used by plugins and Docker Desktop. However, there's currently no public uses of this, and Docker Desktop does not use these functions. This patch deprecates the exported functions as they were meant to be implementation specific for the CLI. If there's a need to provide utilities for manipulating the context-store other than through the CLI itself, we can consider creating an SDK for that purpose. This deprecates: - `RunCreate` and `CreateOptions` - `RunExport` and `ExportOptions` - `RunImport` - `RunRemove` and `RemoveOptions` - `RunUpdate` and `UpdateOptions` - `RunUse` Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 95eeafa5514aea3ebe00b9f19c86c097a9eaf0b6) Signed-off-by: Sebastiaan van Stijn --- cli/command/context/create.go | 80 ++++++++++++++------ cli/command/context/create_test.go | 92 +++++++++++------------ cli/command/context/export-import_test.go | 16 ++-- cli/command/context/export.go | 29 ++++--- cli/command/context/import.go | 21 ++++-- cli/command/context/list_test.go | 8 +- cli/command/context/remove.go | 24 ++++-- cli/command/context/remove_test.go | 12 +-- cli/command/context/update.go | 51 +++++++++---- cli/command/context/update_test.go | 30 ++++---- cli/command/context/use.go | 9 ++- cli/command/context/use_test.go | 18 ++--- 12 files changed, 238 insertions(+), 152 deletions(-) diff --git a/cli/command/context/create.go b/cli/command/context/create.go index 308aa8720069..67d9c0953868 100644 --- a/cli/command/context/create.go +++ b/cli/command/context/create.go @@ -19,6 +19,8 @@ import ( ) // CreateOptions are the options used for creating a context +// +// Deprecated: this type was for internal use and will be removed in the next release. type CreateOptions struct { Name string Description string @@ -30,6 +32,18 @@ type CreateOptions struct { metaData map[string]any } +// createOptions are the options used for creating a context +type createOptions struct { + name string + description string + endpoint map[string]string + from string + + // Additional Metadata to store in the context. This option is not + // currently exposed to the user. + metaData map[string]any +} + func longCreateDescription() string { buf := bytes.NewBuffer(nil) buf.WriteString("Create a context\n\nDocker endpoint config:\n\n") @@ -44,52 +58,68 @@ func longCreateDescription() string { } func newCreateCommand(dockerCLI command.Cli) *cobra.Command { - opts := &CreateOptions{} + opts := createOptions{} cmd := &cobra.Command{ Use: "create [OPTIONS] CONTEXT", Short: "Create a context", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.Name = args[0] - return RunCreate(dockerCLI, opts) + opts.name = args[0] + return runCreate(dockerCLI, &opts) }, Long: longCreateDescription(), ValidArgsFunction: completion.NoComplete, } flags := cmd.Flags() - flags.StringVar(&opts.Description, "description", "", "Description of the context") - flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint") - flags.StringVar(&opts.From, "from", "", "create context from a named context") + flags.StringVar(&opts.description, "description", "", "Description of the context") + flags.StringToStringVar(&opts.endpoint, "docker", nil, "set the docker endpoint") + flags.StringVar(&opts.from, "from", "", "create context from a named context") return cmd } // RunCreate creates a Docker context + +// Deprecated: this function was for internal use and will be removed in the next release. func RunCreate(dockerCLI command.Cli, o *CreateOptions) error { + if o == nil { + o = &CreateOptions{} + } + + return runCreate(dockerCLI, &createOptions{ + name: o.Name, + description: o.Description, + endpoint: o.Docker, + metaData: o.metaData, + }) +} + +// runCreate creates a Docker context +func runCreate(dockerCLI command.Cli, opts *createOptions) error { s := dockerCLI.ContextStore() - err := checkContextNameForCreation(s, o.Name) + err := checkContextNameForCreation(s, opts.name) if err != nil { return err } switch { - case o.From == "" && o.Docker == nil: - err = createFromExistingContext(s, dockerCLI.CurrentContext(), o) - case o.From != "": - err = createFromExistingContext(s, o.From, o) + case opts.from == "" && opts.endpoint == nil: + err = createFromExistingContext(s, dockerCLI.CurrentContext(), opts) + case opts.from != "": + err = createFromExistingContext(s, opts.from, opts) default: - err = createNewContext(s, o) + err = createNewContext(s, opts) } if err == nil { - _, _ = fmt.Fprintln(dockerCLI.Out(), o.Name) - _, _ = fmt.Fprintf(dockerCLI.Err(), "Successfully created context %q\n", o.Name) + _, _ = fmt.Fprintln(dockerCLI.Out(), opts.name) + _, _ = fmt.Fprintf(dockerCLI.Err(), "Successfully created context %q\n", opts.name) } return err } -func createNewContext(contextStore store.ReaderWriter, o *CreateOptions) error { - if o.Docker == nil { +func createNewContext(contextStore store.ReaderWriter, opts *createOptions) error { + if opts.endpoint == nil { return errors.New("docker endpoint configuration is required") } - dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(contextStore, o.Docker) + dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(contextStore, opts.endpoint) if err != nil { return fmt.Errorf("unable to create docker endpoint config: %w", err) } @@ -98,10 +128,10 @@ func createNewContext(contextStore store.ReaderWriter, o *CreateOptions) error { docker.DockerEndpoint: dockerEP, }, Metadata: command.DockerContext{ - Description: o.Description, - AdditionalFields: o.metaData, + Description: opts.description, + AdditionalFields: opts.metaData, }, - Name: o.Name, + Name: opts.name, } contextTLSData := store.ContextTLSData{} if dockerTLS != nil { @@ -115,7 +145,7 @@ func createNewContext(contextStore store.ReaderWriter, o *CreateOptions) error { if err := contextStore.CreateOrUpdate(contextMetadata); err != nil { return err } - return contextStore.ResetTLSMaterial(o.Name, &contextTLSData) + return contextStore.ResetTLSMaterial(opts.name, &contextTLSData) } func checkContextNameForCreation(s store.Reader, name string) error { @@ -131,16 +161,16 @@ func checkContextNameForCreation(s store.Reader, name string) error { return nil } -func createFromExistingContext(s store.ReaderWriter, fromContextName string, o *CreateOptions) error { - if len(o.Docker) != 0 { +func createFromExistingContext(s store.ReaderWriter, fromContextName string, opts *createOptions) error { + if len(opts.endpoint) != 0 { return errors.New("cannot use --docker flag when --from is set") } reader := store.Export(fromContextName, &descriptionDecorator{ Reader: s, - description: o.Description, + description: opts.description, }) defer reader.Close() - return store.Import(o.Name, s, reader) + return store.Import(opts.name, s, reader) } type descriptionDecorator struct { diff --git a/cli/command/context/create_test.go b/cli/command/context/create_test.go index 794f95de04d5..b3344dc9e94b 100644 --- a/cli/command/context/create_test.go +++ b/cli/command/context/create_test.go @@ -60,7 +60,7 @@ func TestCreate(t *testing.T) { assert.NilError(t, cli.ContextStore().CreateOrUpdate(store.Metadata{Name: "existing-context"})) tests := []struct { doc string - options CreateOptions + options createOptions expecterErr string }{ { @@ -69,30 +69,30 @@ func TestCreate(t *testing.T) { }, { doc: "reserved name", - options: CreateOptions{ - Name: "default", + options: createOptions{ + name: "default", }, expecterErr: `"default" is a reserved context name`, }, { doc: "whitespace-only name", - options: CreateOptions{ - Name: " ", + options: createOptions{ + name: " ", }, expecterErr: `context name " " is invalid`, }, { doc: "existing context", - options: CreateOptions{ - Name: "existing-context", + options: createOptions{ + name: "existing-context", }, expecterErr: `context "existing-context" already exists`, }, { doc: "invalid docker host", - options: CreateOptions{ - Name: "invalid-docker-host", - Docker: map[string]string{ + options: createOptions{ + name: "invalid-docker-host", + endpoint: map[string]string{ "host": "some///invalid/host", }, }, @@ -100,27 +100,27 @@ func TestCreate(t *testing.T) { }, { doc: "ssh host with skip-tls-verify=false", - options: CreateOptions{ - Name: "skip-tls-verify-false", - Docker: map[string]string{ + options: createOptions{ + name: "skip-tls-verify-false", + endpoint: map[string]string{ "host": "ssh://example.com,skip-tls-verify=false", }, }, }, { doc: "ssh host with skip-tls-verify=true", - options: CreateOptions{ - Name: "skip-tls-verify-true", - Docker: map[string]string{ + options: createOptions{ + name: "skip-tls-verify-true", + endpoint: map[string]string{ "host": "ssh://example.com,skip-tls-verify=true", }, }, }, { doc: "ssh host with skip-tls-verify=INVALID", - options: CreateOptions{ - Name: "skip-tls-verify-invalid", - Docker: map[string]string{ + options: createOptions{ + name: "skip-tls-verify-invalid", + endpoint: map[string]string{ "host": "ssh://example.com", "skip-tls-verify": "INVALID", }, @@ -129,9 +129,9 @@ func TestCreate(t *testing.T) { }, { doc: "unknown option", - options: CreateOptions{ - Name: "unknown-option", - Docker: map[string]string{ + options: createOptions{ + name: "unknown-option", + endpoint: map[string]string{ "UNKNOWN": "value", }, }, @@ -140,7 +140,7 @@ func TestCreate(t *testing.T) { } for _, tc := range tests { t.Run(tc.doc, func(t *testing.T) { - err := RunCreate(cli, &tc.options) + err := runCreate(cli, &tc.options) if tc.expecterErr == "" { assert.NilError(t, err) } else { @@ -159,9 +159,9 @@ func assertContextCreateLogging(t *testing.T, cli *test.FakeCli, n string) { func TestCreateOrchestratorEmpty(t *testing.T) { cli := makeFakeCli(t) - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{}, }) assert.NilError(t, err) assertContextCreateLogging(t, cli, "test") @@ -187,20 +187,20 @@ func TestCreateFromContext(t *testing.T) { cli := makeFakeCli(t) cli.ResetOutputBuffers() - assert.NilError(t, RunCreate(cli, &CreateOptions{ - Name: "original", - Description: "original description", - Docker: map[string]string{ + assert.NilError(t, runCreate(cli, &createOptions{ + name: "original", + description: "original description", + endpoint: map[string]string{ keyHost: "tcp://42.42.42.42:2375", }, })) assertContextCreateLogging(t, cli, "original") cli.ResetOutputBuffers() - assert.NilError(t, RunCreate(cli, &CreateOptions{ - Name: "dummy", - Description: "dummy description", - Docker: map[string]string{ + assert.NilError(t, runCreate(cli, &createOptions{ + name: "dummy", + description: "dummy description", + endpoint: map[string]string{ keyHost: "tcp://24.24.24.24:2375", }, })) @@ -211,11 +211,11 @@ func TestCreateFromContext(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { cli.ResetOutputBuffers() - err := RunCreate(cli, &CreateOptions{ - From: "original", - Name: tc.name, - Description: tc.description, - Docker: tc.docker, + err := runCreate(cli, &createOptions{ + from: "original", + name: tc.name, + description: tc.description, + endpoint: tc.docker, }) assert.NilError(t, err) assertContextCreateLogging(t, cli, tc.name) @@ -251,10 +251,10 @@ func TestCreateFromCurrent(t *testing.T) { cli := makeFakeCli(t) cli.ResetOutputBuffers() - assert.NilError(t, RunCreate(cli, &CreateOptions{ - Name: "original", - Description: "original description", - Docker: map[string]string{ + assert.NilError(t, runCreate(cli, &createOptions{ + name: "original", + description: "original description", + endpoint: map[string]string{ keyHost: "tcp://42.42.42.42:2375", }, })) @@ -265,9 +265,9 @@ func TestCreateFromCurrent(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { cli.ResetOutputBuffers() - err := RunCreate(cli, &CreateOptions{ - Name: tc.name, - Description: tc.description, + err := runCreate(cli, &createOptions{ + name: tc.name, + description: tc.description, }) assert.NilError(t, err) assertContextCreateLogging(t, cli, tc.name) diff --git a/cli/command/context/export-import_test.go b/cli/command/context/export-import_test.go index 9aabd6ab4490..cfbac778ad6f 100644 --- a/cli/command/context/export-import_test.go +++ b/cli/command/context/export-import_test.go @@ -21,14 +21,11 @@ func TestExportImportWithFile(t *testing.T) { "MyCustomMetadata": t.Name(), }) cli.ErrBuffer().Reset() - assert.NilError(t, RunExport(cli, &ExportOptions{ - ContextName: "test", - Dest: contextFile, - })) + assert.NilError(t, runExport(cli, "test", contextFile)) assert.Equal(t, cli.ErrBuffer().String(), fmt.Sprintf("Written file %q\n", contextFile)) cli.OutBuffer().Reset() cli.ErrBuffer().Reset() - assert.NilError(t, RunImport(cli, "test2", contextFile)) + assert.NilError(t, runImport(cli, "test2", contextFile)) context1, err := cli.ContextStore().GetMetadata("test") assert.NilError(t, err) context2, err := cli.ContextStore().GetMetadata("test2") @@ -55,15 +52,12 @@ func TestExportImportPipe(t *testing.T) { }) cli.ErrBuffer().Reset() cli.OutBuffer().Reset() - assert.NilError(t, RunExport(cli, &ExportOptions{ - ContextName: "test", - Dest: "-", - })) + assert.NilError(t, runExport(cli, "test", "-")) assert.Equal(t, cli.ErrBuffer().String(), "") cli.SetIn(streams.NewIn(io.NopCloser(bytes.NewBuffer(cli.OutBuffer().Bytes())))) cli.OutBuffer().Reset() cli.ErrBuffer().Reset() - assert.NilError(t, RunImport(cli, "test2", "-")) + assert.NilError(t, runImport(cli, "test2", "-")) context1, err := cli.ContextStore().GetMetadata("test") assert.NilError(t, err) context2, err := cli.ContextStore().GetMetadata("test2") @@ -88,6 +82,6 @@ func TestExportExistingFile(t *testing.T) { cli := makeFakeCli(t) cli.ErrBuffer().Reset() assert.NilError(t, os.WriteFile(contextFile, []byte{}, 0o644)) - err := RunExport(cli, &ExportOptions{ContextName: "test", Dest: contextFile}) + err := runExport(cli, "test", contextFile) assert.Assert(t, os.IsExist(err)) } diff --git a/cli/command/context/export.go b/cli/command/context/export.go index 96e35b67505f..90d5b723203d 100644 --- a/cli/command/context/export.go +++ b/cli/command/context/export.go @@ -13,6 +13,8 @@ import ( ) // ExportOptions are the options used for exporting a context +// +// Deprecated: this type was for internal use and will be removed in the next release. type ExportOptions struct { ContextName string Dest string @@ -24,15 +26,14 @@ func newExportCommand(dockerCLI command.Cli) *cobra.Command { Short: "Export a context to a tar archive FILE or a tar stream on STDOUT.", Args: cli.RequiresRangeArgs(1, 2), RunE: func(cmd *cobra.Command, args []string) error { - opts := &ExportOptions{ - ContextName: args[0], - } + contextName := args[0] + var dest string if len(args) == 2 { - opts.Dest = args[1] + dest = args[1] } else { - opts.Dest = opts.ContextName + ".dockercontext" + dest = contextName + ".dockercontext" } - return RunExport(dockerCLI, opts) + return runExport(dockerCLI, contextName, dest) }, ValidArgsFunction: completeContextNames(dockerCLI, 1, true), } @@ -65,11 +66,21 @@ func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error { } // RunExport exports a Docker context +// +// Deprecated: this function was for internal use and will be removed in the next release. func RunExport(dockerCli command.Cli, opts *ExportOptions) error { - if err := store.ValidateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName { + if opts == nil { + opts = &ExportOptions{} + } + return runExport(dockerCli, opts.ContextName, opts.Dest) +} + +// runExport exports a Docker context. +func runExport(dockerCLI command.Cli, contextName string, dest string) error { + if err := store.ValidateContextName(contextName); err != nil && contextName != command.DefaultContextName { return err } - reader := store.Export(opts.ContextName, dockerCli.ContextStore()) + reader := store.Export(contextName, dockerCLI.ContextStore()) defer reader.Close() - return writeTo(dockerCli, reader, opts.Dest) + return writeTo(dockerCLI, reader, dest) } diff --git a/cli/command/context/import.go b/cli/command/context/import.go index 182defcf53dc..aa7a728e1c78 100644 --- a/cli/command/context/import.go +++ b/cli/command/context/import.go @@ -18,7 +18,7 @@ func newImportCommand(dockerCli command.Cli) *cobra.Command { Short: "Import a context from a tar or zip file", Args: cli.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - return RunImport(dockerCli, args[0], args[1]) + return runImport(dockerCli, args[0], args[1]) }, // TODO(thaJeztah): this should also include "-" ValidArgsFunction: completion.FileNames, @@ -27,14 +27,21 @@ func newImportCommand(dockerCli command.Cli) *cobra.Command { } // RunImport imports a Docker context -func RunImport(dockerCli command.Cli, name string, source string) error { - if err := checkContextNameForCreation(dockerCli.ContextStore(), name); err != nil { +// +// Deprecated: this function was for internal use and will be removed in the next release. +func RunImport(dockerCLI command.Cli, name string, source string) error { + return runImport(dockerCLI, name, source) +} + +// runImport imports a Docker context. +func runImport(dockerCLI command.Cli, name string, source string) error { + if err := checkContextNameForCreation(dockerCLI.ContextStore(), name); err != nil { return err } var reader io.Reader if source == "-" { - reader = dockerCli.In() + reader = dockerCLI.In() } else { f, err := os.Open(source) if err != nil { @@ -44,11 +51,11 @@ func RunImport(dockerCli command.Cli, name string, source string) error { reader = f } - if err := store.Import(name, dockerCli.ContextStore(), reader); err != nil { + if err := store.Import(name, dockerCLI.ContextStore(), reader); err != nil { return err } - _, _ = fmt.Fprintln(dockerCli.Out(), name) - _, _ = fmt.Fprintf(dockerCli.Err(), "Successfully imported context %q\n", name) + _, _ = fmt.Fprintln(dockerCLI.Out(), name) + _, _ = fmt.Fprintf(dockerCLI.Err(), "Successfully imported context %q\n", name) return nil } diff --git a/cli/command/context/list_test.go b/cli/command/context/list_test.go index ea7dd1e7c9e0..c98699b74f56 100644 --- a/cli/command/context/list_test.go +++ b/cli/command/context/list_test.go @@ -19,10 +19,10 @@ func createTestContexts(t *testing.T, cli command.Cli, name ...string) { func createTestContext(t *testing.T, cli command.Cli, name string, metaData map[string]any) { t.Helper() - err := RunCreate(cli, &CreateOptions{ - Name: name, - Description: "description of " + name, - Docker: map[string]string{keyHost: "https://someswarmserver.example.com"}, + err := runCreate(cli, &createOptions{ + name: name, + description: "description of " + name, + endpoint: map[string]string{keyHost: "https://someswarmserver.example.com"}, metaData: metaData, }) diff --git a/cli/command/context/remove.go b/cli/command/context/remove.go index 0f73cb1fd749..c3397e8b9c76 100644 --- a/cli/command/context/remove.go +++ b/cli/command/context/remove.go @@ -11,34 +11,48 @@ import ( ) // RemoveOptions are the options used to remove contexts +// +// Deprecated: this type was for internal use and will be removed in the next release. type RemoveOptions struct { Force bool } +// removeOptions are the options used to remove contexts. +type removeOptions struct { + force bool +} + func newRemoveCommand(dockerCLI command.Cli) *cobra.Command { - var opts RemoveOptions + var opts removeOptions cmd := &cobra.Command{ Use: "rm CONTEXT [CONTEXT...]", Aliases: []string{"remove"}, Short: "Remove one or more contexts", Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return RunRemove(dockerCLI, opts, args) + return runRemove(dockerCLI, opts, args) }, ValidArgsFunction: completeContextNames(dockerCLI, -1, false), } - cmd.Flags().BoolVarP(&opts.Force, "force", "f", false, "Force the removal of a context in use") + cmd.Flags().BoolVarP(&opts.force, "force", "f", false, "Force the removal of a context in use") return cmd } // RunRemove removes one or more contexts -func RunRemove(dockerCLI command.Cli, opts RemoveOptions, names []string) error { +// +// Deprecated: this function was for internal use and will be removed in the next release. +func RunRemove(dockerCLI command.Cli, opts removeOptions, names []string) error { + return runRemove(dockerCLI, opts, names) +} + +// runRemove removes one or more contexts. +func runRemove(dockerCLI command.Cli, opts removeOptions, names []string) error { var errs []error currentCtx := dockerCLI.CurrentContext() for _, name := range names { if name == "default" { errs = append(errs, errors.New(`context "default" cannot be removed`)) - } else if err := doRemove(dockerCLI, name, name == currentCtx, opts.Force); err != nil { + } else if err := doRemove(dockerCLI, name, name == currentCtx, opts.force); err != nil { errs = append(errs, err) } else { _, _ = fmt.Fprintln(dockerCLI.Out(), name) diff --git a/cli/command/context/remove_test.go b/cli/command/context/remove_test.go index 9ebb944251d6..d121f39d6df8 100644 --- a/cli/command/context/remove_test.go +++ b/cli/command/context/remove_test.go @@ -14,7 +14,7 @@ import ( func TestRemove(t *testing.T) { cli := makeFakeCli(t) createTestContexts(t, cli, "current", "other") - assert.NilError(t, RunRemove(cli, RemoveOptions{}, []string{"other"})) + assert.NilError(t, runRemove(cli, removeOptions{}, []string{"other"})) _, err := cli.ContextStore().GetMetadata("current") assert.NilError(t, err) _, err = cli.ContextStore().GetMetadata("other") @@ -24,10 +24,10 @@ func TestRemove(t *testing.T) { func TestRemoveNotAContext(t *testing.T) { cli := makeFakeCli(t) createTestContexts(t, cli, "current", "other") - err := RunRemove(cli, RemoveOptions{}, []string{"not-a-context"}) + err := runRemove(cli, removeOptions{}, []string{"not-a-context"}) assert.ErrorContains(t, err, `context "not-a-context" does not exist`) - err = RunRemove(cli, RemoveOptions{Force: true}, []string{"not-a-context"}) + err = runRemove(cli, removeOptions{force: true}, []string{"not-a-context"}) assert.NilError(t, err) } @@ -35,7 +35,7 @@ func TestRemoveCurrent(t *testing.T) { cli := makeFakeCli(t) createTestContexts(t, cli, "current", "other") cli.SetCurrentContext("current") - err := RunRemove(cli, RemoveOptions{}, []string{"current"}) + err := runRemove(cli, removeOptions{}, []string{"current"}) assert.ErrorContains(t, err, `context "current" is in use, set -f flag to force remove`) } @@ -49,7 +49,7 @@ func TestRemoveCurrentForce(t *testing.T) { cli := makeFakeCli(t, withCliConfig(testCfg)) createTestContexts(t, cli, "current", "other") cli.SetCurrentContext("current") - assert.NilError(t, RunRemove(cli, RemoveOptions{Force: true}, []string{"current"})) + assert.NilError(t, runRemove(cli, removeOptions{force: true}, []string{"current"})) reloadedConfig, err := config.Load(configDir) assert.NilError(t, err) assert.Equal(t, "", reloadedConfig.CurrentContext) @@ -59,6 +59,6 @@ func TestRemoveDefault(t *testing.T) { cli := makeFakeCli(t) createTestContext(t, cli, "other", nil) cli.SetCurrentContext("current") - err := RunRemove(cli, RemoveOptions{}, []string{"default"}) + err := runRemove(cli, removeOptions{}, []string{"default"}) assert.ErrorContains(t, err, `context "default" cannot be removed`) } diff --git a/cli/command/context/update.go b/cli/command/context/update.go index 0995c52ef553..2c6a54eda03a 100644 --- a/cli/command/context/update.go +++ b/cli/command/context/update.go @@ -13,12 +13,21 @@ import ( ) // UpdateOptions are the options used to update a context +// +// Deprecated: this type was for internal use and will be removed in the next release. type UpdateOptions struct { Name string Description string Docker map[string]string } +// updateOptions are the options used to update a context. +type updateOptions struct { + name string + description string + endpoint map[string]string +} + func longUpdateDescription() string { buf := bytes.NewBuffer(nil) buf.WriteString("Update a context\n\nDocker endpoint config:\n\n") @@ -33,31 +42,45 @@ func longUpdateDescription() string { } func newUpdateCommand(dockerCLI command.Cli) *cobra.Command { - opts := &UpdateOptions{} + opts := updateOptions{} cmd := &cobra.Command{ Use: "update [OPTIONS] CONTEXT", Short: "Update a context", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.Name = args[0] - return RunUpdate(dockerCLI, opts) + opts.name = args[0] + return runUpdate(dockerCLI, &opts) }, Long: longUpdateDescription(), ValidArgsFunction: completeContextNames(dockerCLI, 1, false), } flags := cmd.Flags() - flags.StringVar(&opts.Description, "description", "", "Description of the context") - flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint") + flags.StringVar(&opts.description, "description", "", "Description of the context") + flags.StringToStringVar(&opts.endpoint, "docker", nil, "set the docker endpoint") return cmd } // RunUpdate updates a Docker context +// +// Deprecated: this function was for internal use and will be removed in the next release. func RunUpdate(dockerCLI command.Cli, o *UpdateOptions) error { - if err := store.ValidateContextName(o.Name); err != nil { + if o == nil { + o = &UpdateOptions{} + } + return runUpdate(dockerCLI, &updateOptions{ + name: o.Name, + description: o.Description, + endpoint: o.Docker, + }) +} + +// runUpdate updates a Docker context. +func runUpdate(dockerCLI command.Cli, opts *updateOptions) error { + if err := store.ValidateContextName(opts.name); err != nil { return err } s := dockerCLI.ContextStore() - c, err := s.GetMetadata(o.Name) + c, err := s.GetMetadata(opts.name) if err != nil { return err } @@ -65,16 +88,16 @@ func RunUpdate(dockerCLI command.Cli, o *UpdateOptions) error { if err != nil { return err } - if o.Description != "" { - dockerContext.Description = o.Description + if opts.description != "" { + dockerContext.Description = opts.description } c.Metadata = dockerContext tlsDataToReset := make(map[string]*store.EndpointTLSData) - if o.Docker != nil { - dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(s, o.Docker) + if opts.endpoint != nil { + dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(s, opts.endpoint) if err != nil { return fmt.Errorf("unable to create docker endpoint config: %w", err) } @@ -88,13 +111,13 @@ func RunUpdate(dockerCLI command.Cli, o *UpdateOptions) error { return err } for ep, tlsData := range tlsDataToReset { - if err := s.ResetEndpointTLSMaterial(o.Name, ep, tlsData); err != nil { + if err := s.ResetEndpointTLSMaterial(opts.name, ep, tlsData); err != nil { return err } } - _, _ = fmt.Fprintln(dockerCLI.Out(), o.Name) - _, _ = fmt.Fprintf(dockerCLI.Err(), "Successfully updated context %q\n", o.Name) + _, _ = fmt.Fprintln(dockerCLI.Out(), opts.name) + _, _ = fmt.Fprintf(dockerCLI.Err(), "Successfully updated context %q\n", opts.name) return nil } diff --git a/cli/command/context/update_test.go b/cli/command/context/update_test.go index 0e4a63914559..3d6493003139 100644 --- a/cli/command/context/update_test.go +++ b/cli/command/context/update_test.go @@ -11,16 +11,16 @@ import ( func TestUpdateDescriptionOnly(t *testing.T) { cli := makeFakeCli(t) - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{}, }) assert.NilError(t, err) cli.OutBuffer().Reset() cli.ErrBuffer().Reset() - assert.NilError(t, RunUpdate(cli, &UpdateOptions{ - Name: "test", - Description: "description", + assert.NilError(t, runUpdate(cli, &updateOptions{ + name: "test", + description: "description", })) c, err := cli.ContextStore().GetMetadata("test") assert.NilError(t, err) @@ -35,9 +35,9 @@ func TestUpdateDescriptionOnly(t *testing.T) { func TestUpdateDockerOnly(t *testing.T) { cli := makeFakeCli(t) createTestContext(t, cli, "test", nil) - assert.NilError(t, RunUpdate(cli, &UpdateOptions{ - Name: "test", - Docker: map[string]string{ + assert.NilError(t, runUpdate(cli, &updateOptions{ + name: "test", + endpoint: map[string]string{ keyHost: "tcp://some-host", }, })) @@ -52,14 +52,14 @@ func TestUpdateDockerOnly(t *testing.T) { func TestUpdateInvalidDockerHost(t *testing.T) { cli := makeFakeCli(t) - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{}, }) assert.NilError(t, err) - err = RunUpdate(cli, &UpdateOptions{ - Name: "test", - Docker: map[string]string{ + err = runUpdate(cli, &updateOptions{ + name: "test", + endpoint: map[string]string{ keyHost: "some///invalid/host", }, }) diff --git a/cli/command/context/use.go b/cli/command/context/use.go index 6b0d927a80af..2fad07eafd4f 100644 --- a/cli/command/context/use.go +++ b/cli/command/context/use.go @@ -17,7 +17,7 @@ func newUseCommand(dockerCLI command.Cli) *cobra.Command { Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - return RunUse(dockerCLI, name) + return runUse(dockerCLI, name) }, ValidArgsFunction: completeContextNames(dockerCLI, 1, false), } @@ -25,7 +25,14 @@ func newUseCommand(dockerCLI command.Cli) *cobra.Command { } // RunUse set the current Docker context +// +// Deprecated: this function was for internal use and will be removed in the next release. func RunUse(dockerCLI command.Cli, name string) error { + return runUse(dockerCLI, name) +} + +// runUse set the current Docker context +func runUse(dockerCLI command.Cli, name string) error { // configValue uses an empty string for "default" var configValue string if name != command.DefaultContextName { diff --git a/cli/command/context/use_test.go b/cli/command/context/use_test.go index ebab2d5e7f5a..0e584b2e6e6c 100644 --- a/cli/command/context/use_test.go +++ b/cli/command/context/use_test.go @@ -23,9 +23,9 @@ func TestUse(t *testing.T) { configFilePath := filepath.Join(configDir, "config.json") testCfg := configfile.New(configFilePath) cli := makeFakeCli(t, withCliConfig(testCfg)) - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{}, }) assert.NilError(t, err) assert.NilError(t, newUseCommand(cli).RunE(nil, []string{"test"})) @@ -89,9 +89,9 @@ func TestUseHostOverride(t *testing.T) { configFilePath := filepath.Join(configDir, "config.json") testCfg := configfile.New(configFilePath) cli := makeFakeCli(t, withCliConfig(testCfg)) - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{}, }) assert.NilError(t, err) @@ -136,9 +136,9 @@ func TestUseHostOverrideEmpty(t *testing.T) { assert.NilError(t, cli.Initialize(flags.NewClientOptions())) } loadCli() - err := RunCreate(cli, &CreateOptions{ - Name: "test", - Docker: map[string]string{"host": socketPath}, + err := runCreate(cli, &createOptions{ + name: "test", + endpoint: map[string]string{"host": socketPath}, }) assert.NilError(t, err)