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 in3126920af1to 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 <github@gone.nl> (cherry picked from commit95eeafa551) Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user