This adds an internal fork of [github.com/docker/docker/registry], taken
at commit [moby@f651a5d]. Git history was not preserved in this fork,
but can be found using the URLs provided.
This fork was created to remove the dependency on the "Moby" codebase,
and because the CLI only needs a subset of its features. The original
package was written specifically for use in the daemon code, and includes
functionality that cannot be used in the CLI.
[github.com/docker/docker/registry]: https://pkg.go.dev/github.com/docker/docker@v28.3.2+incompatible/registry
[moby@49306c6]: 49306c607b/registry
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
84 lines
2.4 KiB
Go
84 lines
2.4 KiB
Go
package registry
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/docker/cli/cli"
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/docker/cli/cli/config/credentials"
|
|
"github.com/docker/cli/internal/oauth/manager"
|
|
"github.com/docker/cli/internal/registry"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// NewLogoutCommand creates a new `docker logout` command
|
|
func NewLogoutCommand(dockerCli command.Cli) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "logout [SERVER]",
|
|
Short: "Log out from a registry",
|
|
Long: "Log out from a registry.\nIf no server is specified, the default is defined by the daemon.",
|
|
Args: cli.RequiresMaxArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
var serverAddress string
|
|
if len(args) > 0 {
|
|
serverAddress = args[0]
|
|
}
|
|
return runLogout(cmd.Context(), dockerCli, serverAddress)
|
|
},
|
|
Annotations: map[string]string{
|
|
"category-top": "9",
|
|
},
|
|
// TODO (thaJeztah) add completion for registries we have authentication stored for
|
|
}
|
|
|
|
return cmd
|
|
}
|
|
|
|
func runLogout(ctx context.Context, dockerCLI command.Cli, serverAddress string) error {
|
|
maybePrintEnvAuthWarning(dockerCLI)
|
|
|
|
var isDefaultRegistry bool
|
|
|
|
if serverAddress == "" {
|
|
serverAddress = registry.IndexServer
|
|
isDefaultRegistry = true
|
|
}
|
|
|
|
var (
|
|
regsToLogout = []string{serverAddress}
|
|
hostnameAddress = serverAddress
|
|
)
|
|
if !isDefaultRegistry {
|
|
hostnameAddress = credentials.ConvertToHostname(serverAddress)
|
|
// the tries below are kept for backward compatibility where a user could have
|
|
// saved the registry in one of the following format.
|
|
regsToLogout = append(regsToLogout, hostnameAddress, "http://"+hostnameAddress, "https://"+hostnameAddress)
|
|
}
|
|
|
|
if isDefaultRegistry {
|
|
store := dockerCLI.ConfigFile().GetCredentialsStore(registry.IndexServer)
|
|
if err := manager.NewManager(store).Logout(ctx); err != nil {
|
|
_, _ = fmt.Fprintln(dockerCLI.Err(), "WARNING:", err)
|
|
}
|
|
}
|
|
|
|
_, _ = fmt.Fprintln(dockerCLI.Out(), "Removing login credentials for", hostnameAddress)
|
|
errs := make(map[string]error)
|
|
for _, r := range regsToLogout {
|
|
if err := dockerCLI.ConfigFile().GetCredentialsStore(r).Erase(r); err != nil {
|
|
errs[r] = err
|
|
}
|
|
}
|
|
|
|
// if at least one removal succeeded, report success. Otherwise report errors
|
|
if len(errs) == len(regsToLogout) {
|
|
_, _ = fmt.Fprintln(dockerCLI.Err(), "WARNING: could not erase credentials:")
|
|
for k, v := range errs {
|
|
_, _ = fmt.Fprintf(dockerCLI.Err(), "%s: %s\n", k, v)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|