diff --git a/cli/command/commands/commands.go b/cli/command/commands/commands.go index d3929293999d..e96a0f1a1ed4 100644 --- a/cli/command/commands/commands.go +++ b/cli/command/commands/commands.go @@ -20,7 +20,6 @@ import ( "github.com/docker/cli/cli/command/stack" "github.com/docker/cli/cli/command/swarm" "github.com/docker/cli/cli/command/system" - "github.com/docker/cli/cli/command/trust" "github.com/docker/cli/cli/command/volume" "github.com/spf13/cobra" ) @@ -53,7 +52,6 @@ func AddCommands(cmd *cobra.Command, dockerCli command.Cli) { network.NewNetworkCommand(dockerCli), plugin.NewPluginCommand(dockerCli), system.NewSystemCommand(dockerCli), - trust.NewTrustCommand(dockerCli), volume.NewVolumeCommand(dockerCli), // orchestration (swarm) commands diff --git a/cmd/docker-trust/main.go b/cmd/docker-trust/main.go new file mode 100644 index 000000000000..96dec635d988 --- /dev/null +++ b/cmd/docker-trust/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/docker/cli/cli" + "github.com/docker/cli/cli-plugins/metadata" + "github.com/docker/cli/cli-plugins/plugin" + "github.com/docker/cli/cli/command" + "github.com/docker/cli/cli/version" + "github.com/docker/cli/cmd/docker-trust/trust" + "go.opentelemetry.io/otel" +) + +func runStandalone(cmd *command.DockerCli) error { + defer flushMetrics(cmd) + executable := os.Args[0] + rootCmd := trust.NewRootCmd(filepath.Base(executable), false, cmd) + return rootCmd.Execute() +} + +// flushMetrics will manually flush metrics from the configured +// meter provider. This is needed when running in standalone mode +// because the meter provider is initialized by the cli library, +// but the mechanism for forcing it to report is not presently +// exposed and not invoked when run in standalone mode. +// There are plans to fix that in the next release, but this is +// needed temporarily until the API for this is more thorough. +func flushMetrics(cmd *command.DockerCli) { + if mp, ok := cmd.MeterProvider().(command.MeterProvider); ok { + if err := mp.ForceFlush(context.Background()); err != nil { + otel.Handle(err) + } + } +} + +func runPlugin(cmd *command.DockerCli) error { + rootCmd := trust.NewRootCmd("trust", true, cmd) + return plugin.RunPlugin(cmd, rootCmd, metadata.Metadata{ + SchemaVersion: "0.1.0", + Vendor: "Docker Inc.", + Version: version.Version, + }) +} + +func run(cmd *command.DockerCli) error { + if plugin.RunningStandalone() { + return runStandalone(cmd) + } + return runPlugin(cmd) +} + +func main() { + cmd, err := command.NewDockerCli() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if err = run(cmd); err == nil { + return + } + + // Check the error from the run function above. + if sterr, ok := err.(cli.StatusError); ok { + if sterr.Status != "" { + _, _ = fmt.Fprintln(cmd.Err(), sterr.Status) + } + // StatusError should only be used for errors, and all errors should + // have a non-zero exit status, so never exit with 0 + if sterr.StatusCode == 0 { + os.Exit(1) + } + os.Exit(sterr.StatusCode) + } + + os.Exit(1) +} diff --git a/cli/command/trust/cmd.go b/cmd/docker-trust/trust/cmd.go similarity index 100% rename from cli/command/trust/cmd.go rename to cmd/docker-trust/trust/cmd.go diff --git a/cmd/docker-trust/trust/commands.go b/cmd/docker-trust/trust/commands.go new file mode 100644 index 000000000000..c9bfa7909f8d --- /dev/null +++ b/cmd/docker-trust/trust/commands.go @@ -0,0 +1,83 @@ +package trust + +import ( + "fmt" + + "github.com/docker/cli-docs-tool/annotation" + "github.com/docker/cli/cli" + "github.com/docker/cli/cli-plugins/plugin" + "github.com/docker/cli/cli/command" + "github.com/docker/cli/cli/debug" + cliflags "github.com/docker/cli/cli/flags" + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +func NewRootCmd(name string, isPlugin bool, dockerCLI *command.DockerCli) *cobra.Command { + var opt rootOptions + cmd := &cobra.Command{ + Use: name, + Short: "Manage trust on Docker images", + Long: `Extended build capabilities with BuildKit`, + Annotations: map[string]string{ + annotation.CodeDelimiter: `"`, + }, + CompletionOptions: cobra.CompletionOptions{ + HiddenDefaultCmd: true, + }, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if opt.debug { + debug.Enable() + } + // cmd.SetContext(appcontext.Context()) + if !isPlugin { + // InstallFlags and SetDefaultOptions are necessary to match + // the plugin mode behavior to handle env vars such as + // DOCKER_TLS, DOCKER_TLS_VERIFY, ... and we also need to use a + // new flagset to avoid conflict with the global debug flag + // that we already handle in the root command otherwise it + // would panic. + nflags := pflag.NewFlagSet(cmd.DisplayName(), pflag.ContinueOnError) + options := cliflags.NewClientOptions() + options.InstallFlags(nflags) + options.SetDefaultOptions(nflags) + return dockerCLI.Initialize(options) + } + return plugin.PersistentPreRunE(cmd, args) + }, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return cmd.Help() + } + _ = cmd.Help() + return cli.StatusError{ + StatusCode: 1, + Status: fmt.Sprintf("ERROR: unknown command: %q", args[0]), + } + }, + } + if !isPlugin { + // match plugin behavior for standalone mode + // https://github.com/docker/cli/blob/6c9eb708fa6d17765d71965f90e1c59cea686ee9/cli-plugins/plugin/plugin.go#L117-L127 + cmd.SilenceUsage = true + cmd.SilenceErrors = true + cmd.TraverseChildren = true + cmd.DisableFlagsInUseLine = true + cli.DisableFlagsInUseLine(cmd) + } + + cmd.AddCommand( + newRevokeCommand(dockerCLI), + newSignCommand(dockerCLI), + newTrustKeyCommand(dockerCLI), + newTrustSignerCommand(dockerCLI), + newInspectCommand(dockerCLI), + ) + + return cmd +} + +type rootOptions struct { + builder string + debug bool +} diff --git a/cli/command/trust/common.go b/cmd/docker-trust/trust/common.go similarity index 100% rename from cli/command/trust/common.go rename to cmd/docker-trust/trust/common.go diff --git a/cli/command/trust/common_test.go b/cmd/docker-trust/trust/common_test.go similarity index 100% rename from cli/command/trust/common_test.go rename to cmd/docker-trust/trust/common_test.go diff --git a/cli/command/trust/formatter.go b/cmd/docker-trust/trust/formatter.go similarity index 100% rename from cli/command/trust/formatter.go rename to cmd/docker-trust/trust/formatter.go diff --git a/cli/command/trust/formatter_test.go b/cmd/docker-trust/trust/formatter_test.go similarity index 100% rename from cli/command/trust/formatter_test.go rename to cmd/docker-trust/trust/formatter_test.go diff --git a/cli/command/trust/helpers.go b/cmd/docker-trust/trust/helpers.go similarity index 100% rename from cli/command/trust/helpers.go rename to cmd/docker-trust/trust/helpers.go diff --git a/cli/command/trust/inspect.go b/cmd/docker-trust/trust/inspect.go similarity index 100% rename from cli/command/trust/inspect.go rename to cmd/docker-trust/trust/inspect.go diff --git a/cli/command/trust/inspect_pretty.go b/cmd/docker-trust/trust/inspect_pretty.go similarity index 100% rename from cli/command/trust/inspect_pretty.go rename to cmd/docker-trust/trust/inspect_pretty.go diff --git a/cli/command/trust/inspect_pretty_test.go b/cmd/docker-trust/trust/inspect_pretty_test.go similarity index 100% rename from cli/command/trust/inspect_pretty_test.go rename to cmd/docker-trust/trust/inspect_pretty_test.go diff --git a/cli/command/trust/inspect_test.go b/cmd/docker-trust/trust/inspect_test.go similarity index 100% rename from cli/command/trust/inspect_test.go rename to cmd/docker-trust/trust/inspect_test.go diff --git a/cli/command/trust/key.go b/cmd/docker-trust/trust/key.go similarity index 100% rename from cli/command/trust/key.go rename to cmd/docker-trust/trust/key.go diff --git a/cli/command/trust/key_generate.go b/cmd/docker-trust/trust/key_generate.go similarity index 100% rename from cli/command/trust/key_generate.go rename to cmd/docker-trust/trust/key_generate.go diff --git a/cli/command/trust/key_generate_test.go b/cmd/docker-trust/trust/key_generate_test.go similarity index 100% rename from cli/command/trust/key_generate_test.go rename to cmd/docker-trust/trust/key_generate_test.go diff --git a/cli/command/trust/key_load.go b/cmd/docker-trust/trust/key_load.go similarity index 100% rename from cli/command/trust/key_load.go rename to cmd/docker-trust/trust/key_load.go diff --git a/cli/command/trust/key_load_test.go b/cmd/docker-trust/trust/key_load_test.go similarity index 100% rename from cli/command/trust/key_load_test.go rename to cmd/docker-trust/trust/key_load_test.go diff --git a/cli/command/trust/revoke.go b/cmd/docker-trust/trust/revoke.go similarity index 100% rename from cli/command/trust/revoke.go rename to cmd/docker-trust/trust/revoke.go diff --git a/cli/command/trust/revoke_test.go b/cmd/docker-trust/trust/revoke_test.go similarity index 100% rename from cli/command/trust/revoke_test.go rename to cmd/docker-trust/trust/revoke_test.go diff --git a/cli/command/trust/sign.go b/cmd/docker-trust/trust/sign.go similarity index 100% rename from cli/command/trust/sign.go rename to cmd/docker-trust/trust/sign.go diff --git a/cli/command/trust/sign_test.go b/cmd/docker-trust/trust/sign_test.go similarity index 100% rename from cli/command/trust/sign_test.go rename to cmd/docker-trust/trust/sign_test.go diff --git a/cli/command/trust/signer.go b/cmd/docker-trust/trust/signer.go similarity index 100% rename from cli/command/trust/signer.go rename to cmd/docker-trust/trust/signer.go diff --git a/cli/command/trust/signer_add.go b/cmd/docker-trust/trust/signer_add.go similarity index 100% rename from cli/command/trust/signer_add.go rename to cmd/docker-trust/trust/signer_add.go diff --git a/cli/command/trust/signer_add_test.go b/cmd/docker-trust/trust/signer_add_test.go similarity index 100% rename from cli/command/trust/signer_add_test.go rename to cmd/docker-trust/trust/signer_add_test.go diff --git a/cli/command/trust/signer_remove.go b/cmd/docker-trust/trust/signer_remove.go similarity index 100% rename from cli/command/trust/signer_remove.go rename to cmd/docker-trust/trust/signer_remove.go diff --git a/cli/command/trust/signer_remove_test.go b/cmd/docker-trust/trust/signer_remove_test.go similarity index 100% rename from cli/command/trust/signer_remove_test.go rename to cmd/docker-trust/trust/signer_remove_test.go diff --git a/cli/command/trust/testdata/trust-inspect-empty-repo.golden b/cmd/docker-trust/trust/testdata/trust-inspect-empty-repo.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-empty-repo.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-empty-repo.golden diff --git a/cli/command/trust/testdata/trust-inspect-full-repo-no-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-full-repo-no-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-full-repo-no-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-full-repo-no-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-full-repo-with-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-full-repo-with-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-full-repo-with-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-full-repo-with-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-multiple-repos-with-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-multiple-repos-with-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-multiple-repos-with-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-multiple-repos-with-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-one-tag-no-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-one-tag-no-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-one-tag-no-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-one-tag-no-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-pretty-full-repo-no-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-pretty-full-repo-no-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-pretty-full-repo-no-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-pretty-full-repo-no-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-pretty-full-repo-with-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-pretty-full-repo-with-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-pretty-full-repo-with-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-pretty-full-repo-with-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-pretty-one-tag-no-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-pretty-one-tag-no-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-pretty-one-tag-no-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-pretty-one-tag-no-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-pretty-unsigned-tag-with-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-pretty-unsigned-tag-with-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-pretty-unsigned-tag-with-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-pretty-unsigned-tag-with-signers.golden diff --git a/cli/command/trust/testdata/trust-inspect-uninitialized.golden b/cmd/docker-trust/trust/testdata/trust-inspect-uninitialized.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-uninitialized.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-uninitialized.golden diff --git a/cli/command/trust/testdata/trust-inspect-unsigned-tag-with-signers.golden b/cmd/docker-trust/trust/testdata/trust-inspect-unsigned-tag-with-signers.golden similarity index 100% rename from cli/command/trust/testdata/trust-inspect-unsigned-tag-with-signers.golden rename to cmd/docker-trust/trust/testdata/trust-inspect-unsigned-tag-with-signers.golden diff --git a/cli/command/trust/testdata/trust-revoke-prompt-termination.golden b/cmd/docker-trust/trust/testdata/trust-revoke-prompt-termination.golden similarity index 100% rename from cli/command/trust/testdata/trust-revoke-prompt-termination.golden rename to cmd/docker-trust/trust/testdata/trust-revoke-prompt-termination.golden