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  }