github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/context/options.go (about) 1 package context 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/docker/cli/cli/context" 9 "github.com/docker/cli/cli/context/docker" 10 "github.com/docker/cli/cli/context/store" 11 "github.com/docker/docker/client" 12 "github.com/pkg/errors" 13 ) 14 15 const ( 16 keyFrom = "from" 17 keyHost = "host" 18 keyCA = "ca" 19 keyCert = "cert" 20 keyKey = "key" 21 keySkipTLSVerify = "skip-tls-verify" 22 ) 23 24 type configKeyDescription struct { 25 name string 26 description string 27 } 28 29 var ( 30 allowedDockerConfigKeys = map[string]struct{}{ 31 keyFrom: {}, 32 keyHost: {}, 33 keyCA: {}, 34 keyCert: {}, 35 keyKey: {}, 36 keySkipTLSVerify: {}, 37 } 38 dockerConfigKeysDescriptions = []configKeyDescription{ 39 { 40 name: keyFrom, 41 description: "Copy named context's Docker endpoint configuration", 42 }, 43 { 44 name: keyHost, 45 description: "Docker endpoint on which to connect", 46 }, 47 { 48 name: keyCA, 49 description: "Trust certs signed only by this CA", 50 }, 51 { 52 name: keyCert, 53 description: "Path to TLS certificate file", 54 }, 55 { 56 name: keyKey, 57 description: "Path to TLS key file", 58 }, 59 { 60 name: keySkipTLSVerify, 61 description: "Skip TLS certificate validation", 62 }, 63 } 64 ) 65 66 func parseBool(config map[string]string, name string) (bool, error) { 67 strVal, ok := config[name] 68 if !ok { 69 return false, nil 70 } 71 res, err := strconv.ParseBool(strVal) 72 return res, errors.Wrap(err, name) 73 } 74 75 func validateConfig(config map[string]string, allowedKeys map[string]struct{}) error { 76 var errs []string 77 for k := range config { 78 if _, ok := allowedKeys[k]; !ok { 79 errs = append(errs, fmt.Sprintf("%s: unrecognized config key", k)) 80 } 81 } 82 if len(errs) == 0 { 83 return nil 84 } 85 return errors.New(strings.Join(errs, "\n")) 86 } 87 88 func getDockerEndpoint(contextStore store.Reader, config map[string]string) (docker.Endpoint, error) { 89 if err := validateConfig(config, allowedDockerConfigKeys); err != nil { 90 return docker.Endpoint{}, err 91 } 92 if contextName, ok := config[keyFrom]; ok { 93 metadata, err := contextStore.GetMetadata(contextName) 94 if err != nil { 95 return docker.Endpoint{}, err 96 } 97 if ep, ok := metadata.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta); ok { 98 return docker.Endpoint{EndpointMeta: ep}, nil 99 } 100 return docker.Endpoint{}, errors.Errorf("unable to get endpoint from context %q", contextName) 101 } 102 tlsData, err := context.TLSDataFromFiles(config[keyCA], config[keyCert], config[keyKey]) 103 if err != nil { 104 return docker.Endpoint{}, err 105 } 106 skipTLSVerify, err := parseBool(config, keySkipTLSVerify) 107 if err != nil { 108 return docker.Endpoint{}, err 109 } 110 ep := docker.Endpoint{ 111 EndpointMeta: docker.EndpointMeta{ 112 Host: config[keyHost], 113 SkipTLSVerify: skipTLSVerify, 114 }, 115 TLSData: tlsData, 116 } 117 // try to resolve a docker client, validating the configuration 118 opts, err := ep.ClientOpts() 119 if err != nil { 120 return docker.Endpoint{}, errors.Wrap(err, "invalid docker endpoint options") 121 } 122 if _, err := client.NewClientWithOpts(opts...); err != nil { 123 return docker.Endpoint{}, errors.Wrap(err, "unable to apply docker endpoint options") 124 } 125 return ep, nil 126 } 127 128 func getDockerEndpointMetadataAndTLS(contextStore store.Reader, config map[string]string) (docker.EndpointMeta, *store.EndpointTLSData, error) { 129 ep, err := getDockerEndpoint(contextStore, config) 130 if err != nil { 131 return docker.EndpointMeta{}, nil, err 132 } 133 return ep.EndpointMeta, ep.TLSData.ToStoreTLSData(), nil 134 }