command-runner/internal/containers/docker/docker_connect.go (98 lines of code) (raw):

package docker import ( "context" "fmt" "os" "strings" "github.com/aws/codecatalyst-runner-cli/command-runner/pkg/common" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/connhelper" "github.com/docker/cli/cli/context/docker" "github.com/docker/cli/cli/context/store" cliflags "github.com/docker/cli/cli/flags" "github.com/docker/docker/client" "github.com/rs/zerolog/log" ) // getDockerEndpointOpts results the endpoint for current docker context func getDockerEndpointOpts(ctx context.Context) ([]client.Opt, error) { opts := &cliflags.ClientOptions{} storeConfig := command.DefaultContextStoreConfig() contextStore := &command.ContextStoreWithDefault{ Store: store.New(config.ContextStoreDir(), storeConfig), Resolver: func() (*command.DefaultContext, error) { return command.ResolveDefaultContext(opts, storeConfig) }, } endpoint, err := resolveDockerEndpoint(ctx, contextStore, resolveContextName()) if err != nil { return nil, fmt.Errorf("unable to resolve docker endpoint: %w", err) } return endpoint.ClientOpts() } // resolveDockerEndpoint from store func resolveDockerEndpoint(ctx context.Context, s store.Reader, contextName string) (docker.Endpoint, error) { if s == nil { return docker.Endpoint{}, fmt.Errorf("no context store initialized") } log.Ctx(ctx).Debug().Msgf("Using docker context '%s'", contextName) ctxMeta, err := s.GetMetadata(contextName) if err != nil { return docker.Endpoint{}, err } epMeta, err := docker.EndpointFromContext(ctxMeta) if err != nil { return docker.Endpoint{}, err } log.Ctx(ctx).Debug().Msgf("%sdocker context=%s host=%s", logPrefix, contextName, epMeta.Host) return docker.WithTLSData(s, contextName, epMeta) } // resolveContextName from environment variable or use current func resolveContextName() string { cfg := config.LoadDefaultConfigFile(os.Stderr) if os.Getenv(client.EnvOverrideHost) != "" { return command.DefaultContextName } if ctxName := os.Getenv(command.EnvOverrideContext); ctxName != "" { return ctxName } if cfg != nil && cfg.CurrentContext != "" { // We don't validate if this context exists: errors may occur when trying to use it. return cfg.CurrentContext } return command.DefaultContextName } // getDockerClient returns the Docker APIClient func getDockerClient(ctx context.Context) (cli client.APIClient, err error) { opts, err := getDockerEndpointOpts(ctx) if err != nil { return nil, err } dockerHost := os.Getenv("DOCKER_HOST") if strings.HasPrefix(dockerHost, "ssh://") { var helper *connhelper.ConnectionHelper helper, err = connhelper.GetConnectionHelper(dockerHost) if err != nil { return nil, err } cli, err = client.NewClientWithOpts( client.WithHost(helper.Host), client.WithDialContext(helper.Dialer), ) } else { cli, err = client.NewClientWithOpts(opts...) } if err != nil { return nil, fmt.Errorf("failed to connect to docker daemon: %w", err) } cli.NegotiateAPIVersion(ctx) return cli, nil } func (cr *dockerContainer) connect() common.Executor { return func(ctx context.Context) error { if cr.cli != nil { return nil } cli, err := getDockerClient(ctx) if err != nil { return err } cr.cli = cli return nil } }