mirror of https://github.com/docker/cli.git
136 lines
3.5 KiB
Go
136 lines
3.5 KiB
Go
package context
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/docker/cli/cli/context"
|
|
"github.com/docker/cli/cli/context/docker"
|
|
"github.com/docker/cli/cli/context/store"
|
|
"github.com/docker/docker/client"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
keyFrom = "from"
|
|
keyHost = "host"
|
|
keyCA = "ca"
|
|
keyCert = "cert"
|
|
keyKey = "key"
|
|
keySkipTLSVerify = "skip-tls-verify"
|
|
)
|
|
|
|
type configKeyDescription struct {
|
|
name string
|
|
description string
|
|
}
|
|
|
|
var (
|
|
allowedDockerConfigKeys = map[string]struct{}{
|
|
keyFrom: {},
|
|
keyHost: {},
|
|
keyCA: {},
|
|
keyCert: {},
|
|
keyKey: {},
|
|
keySkipTLSVerify: {},
|
|
}
|
|
dockerConfigKeysDescriptions = []configKeyDescription{
|
|
{
|
|
name: keyFrom,
|
|
description: "Copy named context's Docker endpoint configuration",
|
|
},
|
|
{
|
|
name: keyHost,
|
|
description: "Docker endpoint on which to connect",
|
|
},
|
|
{
|
|
name: keyCA,
|
|
description: "Trust certs signed only by this CA",
|
|
},
|
|
{
|
|
name: keyCert,
|
|
description: "Path to TLS certificate file",
|
|
},
|
|
{
|
|
name: keyKey,
|
|
description: "Path to TLS key file",
|
|
},
|
|
{
|
|
name: keySkipTLSVerify,
|
|
description: "Skip TLS certificate validation",
|
|
},
|
|
}
|
|
)
|
|
|
|
func parseBool(config map[string]string, name string) (bool, error) {
|
|
strVal, ok := config[name]
|
|
if !ok {
|
|
return false, nil
|
|
}
|
|
res, err := strconv.ParseBool(strVal)
|
|
return res, errors.Wrap(err, name)
|
|
}
|
|
|
|
func validateConfig(config map[string]string, allowedKeys map[string]struct{}) error {
|
|
var errs []string
|
|
for k := range config {
|
|
if _, ok := allowedKeys[k]; !ok {
|
|
errs = append(errs, fmt.Sprintf("%s: unrecognized config key", k))
|
|
}
|
|
}
|
|
if len(errs) == 0 {
|
|
return nil
|
|
}
|
|
return errors.New(strings.Join(errs, "\n"))
|
|
}
|
|
|
|
func getDockerEndpoint(dockerCli command.Cli, config map[string]string) (docker.Endpoint, error) {
|
|
if err := validateConfig(config, allowedDockerConfigKeys); err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
if contextName, ok := config[keyFrom]; ok {
|
|
metadata, err := dockerCli.ContextStore().GetMetadata(contextName)
|
|
if err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
if ep, ok := metadata.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta); ok {
|
|
return docker.Endpoint{EndpointMeta: ep}, nil
|
|
}
|
|
return docker.Endpoint{}, errors.Errorf("unable to get endpoint from context %q", contextName)
|
|
}
|
|
tlsData, err := context.TLSDataFromFiles(config[keyCA], config[keyCert], config[keyKey])
|
|
if err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
skipTLSVerify, err := parseBool(config, keySkipTLSVerify)
|
|
if err != nil {
|
|
return docker.Endpoint{}, err
|
|
}
|
|
ep := docker.Endpoint{
|
|
EndpointMeta: docker.EndpointMeta{
|
|
Host: config[keyHost],
|
|
SkipTLSVerify: skipTLSVerify,
|
|
},
|
|
TLSData: tlsData,
|
|
}
|
|
// try to resolve a docker client, validating the configuration
|
|
opts, err := ep.ClientOpts()
|
|
if err != nil {
|
|
return docker.Endpoint{}, errors.Wrap(err, "invalid docker endpoint options")
|
|
}
|
|
if _, err := client.NewClientWithOpts(opts...); err != nil {
|
|
return docker.Endpoint{}, errors.Wrap(err, "unable to apply docker endpoint options")
|
|
}
|
|
return ep, nil
|
|
}
|
|
|
|
func getDockerEndpointMetadataAndTLS(dockerCli command.Cli, config map[string]string) (docker.EndpointMeta, *store.EndpointTLSData, error) {
|
|
ep, err := getDockerEndpoint(dockerCli, config)
|
|
if err != nil {
|
|
return docker.EndpointMeta{}, nil, err
|
|
}
|
|
return ep.EndpointMeta, ep.TLSData.ToStoreTLSData(), nil
|
|
}
|