diff --git a/cli/command/manifest/annotate.go b/cli/command/manifest/annotate.go index a9507deb73f0..7231d161e1de 100644 --- a/cli/command/manifest/annotate.go +++ b/cli/command/manifest/annotate.go @@ -84,7 +84,7 @@ func newAnnotateCommand(dockerCLI command.Cli) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { opts.target = args[0] opts.image = args[1] - return runManifestAnnotate(dockerCLI, opts) + return runManifestAnnotate(dockerCLI, cmd, opts) }, DisableFlagsInUseLine: true, } @@ -100,7 +100,7 @@ func newAnnotateCommand(dockerCLI command.Cli) *cobra.Command { return cmd } -func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error { +func runManifestAnnotate(dockerCLI command.Cli, cmd *cobra.Command, opts annotateOptions) error { targetRef, err := normalizeReference(opts.target) if err != nil { return fmt.Errorf("annotate: error parsing name for manifest list %s: %w", opts.target, err) @@ -132,7 +132,9 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error { for _, osFeature := range opts.osFeatures { imageManifest.Descriptor.Platform.OSFeatures = appendIfUnique(imageManifest.Descriptor.Platform.OSFeatures, osFeature) } - if opts.variant != "" { + // An empty --variant is how you clear one. The zero value is also the + // default when the flag is omitted, so only write it when it was set. + if cmd.Flags().Changed("variant") { imageManifest.Descriptor.Platform.Variant = opts.variant } if opts.osVersion != "" { diff --git a/cli/command/manifest/annotate_test.go b/cli/command/manifest/annotate_test.go index f2c924e45ffc..5a7527e2259e 100644 --- a/cli/command/manifest/annotate_test.go +++ b/cli/command/manifest/annotate_test.go @@ -11,6 +11,38 @@ import ( "gotest.tools/v3/golden" ) +func TestManifestAnnotateClearsVariant(t *testing.T) { + manifestStore := store.NewStore(t.TempDir()) + + cli := test.NewFakeCli(nil) + cli.SetManifestStore(manifestStore) + namedRef := ref(t, "alpine:3.0") + imageManifest := fullImageManifest(t, namedRef) + imageManifest.Descriptor.Platform.Variant = "v7" + err := manifestStore.Save(ref(t, "list:v1"), namedRef, imageManifest) + assert.NilError(t, err) + + cmd := newAnnotateCommand(cli) + cmd.SetArgs([]string{"--os", "linux", "example.com/list:v1", "example.com/alpine:3.0"}) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + assert.NilError(t, cmd.Execute()) + + got, err := manifestStore.Get(ref(t, "list:v1"), namedRef) + assert.NilError(t, err) + assert.Check(t, is.Equal("v7", got.Descriptor.Platform.Variant)) + + cmd = newAnnotateCommand(cli) + cmd.SetArgs([]string{"--variant", "", "example.com/list:v1", "example.com/alpine:3.0"}) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + assert.NilError(t, cmd.Execute()) + + got, err = manifestStore.Get(ref(t, "list:v1"), namedRef) + assert.NilError(t, err) + assert.Check(t, is.Equal("", got.Descriptor.Platform.Variant)) +} + func TestManifestAnnotateError(t *testing.T) { testCases := []struct { args []string