vendor: update docker/cli to 8667ccd

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2022-02-27 00:35:39 +01:00
parent f62c02329e
commit 971b5d2b73
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
35 changed files with 495 additions and 527 deletions

View File

@ -43,21 +43,19 @@ func init() {
}
func main() {
if os.Getenv("DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND") == "" {
if len(os.Args) < 2 || os.Args[1] != manager.MetadataSubcommandName {
dockerCli, err := command.NewDockerCli()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
opts := cliflags.NewClientOptions()
dockerCli.Initialize(opts)
rootCmd := commands.NewRootCmd(os.Args[0], false, dockerCli)
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
os.Exit(0)
if plugin.RunningStandalone() {
dockerCli, err := command.NewDockerCli()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
opts := cliflags.NewClientOptions()
dockerCli.Initialize(opts)
rootCmd := commands.NewRootCmd(os.Args[0], false, dockerCli)
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
os.Exit(0)
}
dockerCli, err := command.NewDockerCli()

View File

@ -8,13 +8,13 @@ import (
"github.com/docker/buildx/build"
"github.com/docker/buildx/driver"
ctxkube "github.com/docker/buildx/driver/kubernetes/context"
"github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/kubernetes"
ctxstore "github.com/docker/cli/cli/context/store"
dopts "github.com/docker/cli/opts"
dockerclient "github.com/docker/docker/client"
@ -150,7 +150,7 @@ func configFromContext(endpointName string, s ctxstore.Reader) (clientcmd.Client
}
return clientcmd.NewDefaultClientConfig(*apiConfig, &clientcmd.ConfigOverrides{}), nil
}
return kubernetes.ConfigFromContext(endpointName, s)
return ctxkube.ConfigFromContext(endpointName, s)
}
// clientForEndpoint returns a docker client for an endpoint

View File

@ -1,4 +1,4 @@
package kubernetes
package context
const (
// KubernetesEndpoint is the kubernetes endpoint name in a stored context

View File

@ -0,0 +1,225 @@
package context
import (
"io/ioutil"
"os"
"testing"
"github.com/docker/cli/cli/context"
"github.com/docker/cli/cli/context/store"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
func testEndpoint(server, defaultNamespace string, ca, cert, key []byte, skipTLSVerify bool) Endpoint {
var tlsData *context.TLSData
if ca != nil || cert != nil || key != nil {
tlsData = &context.TLSData{
CA: ca,
Cert: cert,
Key: key,
}
}
return Endpoint{
EndpointMeta: EndpointMeta{
EndpointMetaBase: context.EndpointMetaBase{
Host: server,
SkipTLSVerify: skipTLSVerify,
},
DefaultNamespace: defaultNamespace,
},
TLSData: tlsData,
}
}
var testStoreCfg = store.NewConfig(
func() interface{} {
return &map[string]interface{}{}
},
store.EndpointTypeGetter(KubernetesEndpoint, func() interface{} { return &EndpointMeta{} }),
)
func TestSaveLoadContexts(t *testing.T) {
storeDir, err := ioutil.TempDir("", "test-load-save-k8-context")
require.NoError(t, err)
defer os.RemoveAll(storeDir)
store := store.New(storeDir, testStoreCfg)
require.NoError(t, save(store, testEndpoint("https://test", "test", nil, nil, nil, false), "raw-notls"))
require.NoError(t, save(store, testEndpoint("https://test", "test", nil, nil, nil, true), "raw-notls-skip"))
require.NoError(t, save(store, testEndpoint("https://test", "test", []byte("ca"), []byte("cert"), []byte("key"), true), "raw-tls"))
kcFile, err := ioutil.TempFile(os.TempDir(), "test-load-save-k8-context")
require.NoError(t, err)
defer os.Remove(kcFile.Name())
defer kcFile.Close()
cfg := clientcmdapi.NewConfig()
cfg.AuthInfos["user"] = clientcmdapi.NewAuthInfo()
cfg.Contexts["context1"] = clientcmdapi.NewContext()
cfg.Clusters["cluster1"] = clientcmdapi.NewCluster()
cfg.Contexts["context2"] = clientcmdapi.NewContext()
cfg.Clusters["cluster2"] = clientcmdapi.NewCluster()
cfg.AuthInfos["user"].ClientCertificateData = []byte("cert")
cfg.AuthInfos["user"].ClientKeyData = []byte("key")
cfg.Clusters["cluster1"].Server = "https://server1"
cfg.Clusters["cluster1"].InsecureSkipTLSVerify = true
cfg.Clusters["cluster2"].Server = "https://server2"
cfg.Clusters["cluster2"].CertificateAuthorityData = []byte("ca")
cfg.Contexts["context1"].AuthInfo = "user"
cfg.Contexts["context1"].Cluster = "cluster1"
cfg.Contexts["context1"].Namespace = "namespace1"
cfg.Contexts["context2"].AuthInfo = "user"
cfg.Contexts["context2"].Cluster = "cluster2"
cfg.Contexts["context2"].Namespace = "namespace2"
cfg.CurrentContext = "context1"
cfgData, err := clientcmd.Write(*cfg)
require.NoError(t, err)
_, err = kcFile.Write(cfgData)
require.NoError(t, err)
kcFile.Close()
epDefault, err := FromKubeConfig(kcFile.Name(), "", "")
require.NoError(t, err)
epContext2, err := FromKubeConfig(kcFile.Name(), "context2", "namespace-override")
require.NoError(t, err)
require.NoError(t, save(store, epDefault, "embed-default-context"))
require.NoError(t, save(store, epContext2, "embed-context2"))
rawNoTLSMeta, err := store.GetMetadata("raw-notls")
require.NoError(t, err)
rawNoTLSSkipMeta, err := store.GetMetadata("raw-notls-skip")
require.NoError(t, err)
rawTLSMeta, err := store.GetMetadata("raw-tls")
require.NoError(t, err)
embededDefaultMeta, err := store.GetMetadata("embed-default-context")
require.NoError(t, err)
embededContext2Meta, err := store.GetMetadata("embed-context2")
require.NoError(t, err)
rawNoTLS := EndpointFromContext(rawNoTLSMeta)
rawNoTLSSkip := EndpointFromContext(rawNoTLSSkipMeta)
rawTLS := EndpointFromContext(rawTLSMeta)
embededDefault := EndpointFromContext(embededDefaultMeta)
embededContext2 := EndpointFromContext(embededContext2Meta)
rawNoTLSEP, err := rawNoTLS.WithTLSData(store, "raw-notls")
require.NoError(t, err)
checkClientConfig(t, rawNoTLSEP, "https://test", "test", nil, nil, nil, false)
rawNoTLSSkipEP, err := rawNoTLSSkip.WithTLSData(store, "raw-notls-skip")
require.NoError(t, err)
checkClientConfig(t, rawNoTLSSkipEP, "https://test", "test", nil, nil, nil, true)
rawTLSEP, err := rawTLS.WithTLSData(store, "raw-tls")
require.NoError(t, err)
checkClientConfig(t, rawTLSEP, "https://test", "test", []byte("ca"), []byte("cert"), []byte("key"), true)
embededDefaultEP, err := embededDefault.WithTLSData(store, "embed-default-context")
require.NoError(t, err)
checkClientConfig(t, embededDefaultEP, "https://server1", "namespace1", nil, []byte("cert"), []byte("key"), true)
embededContext2EP, err := embededContext2.WithTLSData(store, "embed-context2")
require.NoError(t, err)
checkClientConfig(t, embededContext2EP, "https://server2", "namespace-override", []byte("ca"), []byte("cert"), []byte("key"), false)
}
func checkClientConfig(t *testing.T, ep Endpoint, server, namespace string, ca, cert, key []byte, skipTLSVerify bool) {
config := ep.KubernetesConfig()
cfg, err := config.ClientConfig()
require.NoError(t, err)
ns, _, _ := config.Namespace()
assert.Equal(t, server, cfg.Host)
assert.Equal(t, namespace, ns)
assert.Equal(t, ca, cfg.CAData)
assert.Equal(t, cert, cfg.CertData)
assert.Equal(t, key, cfg.KeyData)
assert.Equal(t, skipTLSVerify, cfg.Insecure)
}
func save(s store.Writer, ep Endpoint, name string) error {
meta := store.Metadata{
Endpoints: map[string]interface{}{
KubernetesEndpoint: ep.EndpointMeta,
},
Name: name,
}
if err := s.CreateOrUpdate(meta); err != nil {
return err
}
return s.ResetEndpointTLSMaterial(name, KubernetesEndpoint, ep.TLSData.ToStoreTLSData())
}
func TestSaveLoadGKEConfig(t *testing.T) {
storeDir, err := ioutil.TempDir("", t.Name())
require.NoError(t, err)
defer os.RemoveAll(storeDir)
store := store.New(storeDir, testStoreCfg)
cfg, err := clientcmd.LoadFromFile("fixtures/gke-kubeconfig")
require.NoError(t, err)
clientCfg := clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{})
expectedCfg, err := clientCfg.ClientConfig()
require.NoError(t, err)
ep, err := FromKubeConfig("fixtures/gke-kubeconfig", "", "")
require.NoError(t, err)
require.NoError(t, save(store, ep, "gke-context"))
persistedMetadata, err := store.GetMetadata("gke-context")
require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil)
persistedEP, err := persistedEPMeta.WithTLSData(store, "gke-context")
require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig()
actualCfg, err := persistedCfg.ClientConfig()
require.NoError(t, err)
assert.Equal(t, expectedCfg.AuthProvider, actualCfg.AuthProvider)
}
func TestSaveLoadEKSConfig(t *testing.T) {
storeDir, err := ioutil.TempDir("", t.Name())
require.NoError(t, err)
defer os.RemoveAll(storeDir)
store := store.New(storeDir, testStoreCfg)
cfg, err := clientcmd.LoadFromFile("fixtures/eks-kubeconfig")
require.NoError(t, err)
clientCfg := clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{})
expectedCfg, err := clientCfg.ClientConfig()
require.NoError(t, err)
ep, err := FromKubeConfig("fixtures/eks-kubeconfig", "", "")
require.NoError(t, err)
require.NoError(t, save(store, ep, "eks-context"))
persistedMetadata, err := store.GetMetadata("eks-context")
require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil)
persistedEP, err := persistedEPMeta.WithTLSData(store, "eks-context")
require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig()
actualCfg, err := persistedCfg.ClientConfig()
require.NoError(t, err)
assert.Equal(t, expectedCfg.ExecProvider, actualCfg.ExecProvider)
}
func TestSaveLoadK3SConfig(t *testing.T) {
storeDir, err := ioutil.TempDir("", t.Name())
require.NoError(t, err)
defer os.RemoveAll(storeDir)
store := store.New(storeDir, testStoreCfg)
cfg, err := clientcmd.LoadFromFile("fixtures/k3s-kubeconfig")
require.NoError(t, err)
clientCfg := clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{})
expectedCfg, err := clientCfg.ClientConfig()
require.NoError(t, err)
ep, err := FromKubeConfig("fixtures/k3s-kubeconfig", "", "")
require.NoError(t, err)
require.NoError(t, save(store, ep, "k3s-context"))
persistedMetadata, err := store.GetMetadata("k3s-context")
require.NoError(t, err)
persistedEPMeta := EndpointFromContext(persistedMetadata)
assert.True(t, persistedEPMeta != nil)
persistedEP, err := persistedEPMeta.WithTLSData(store, "k3s-context")
require.NoError(t, err)
persistedCfg := persistedEP.KubernetesConfig()
actualCfg, err := persistedCfg.ClientConfig()
require.NoError(t, err)
assert.True(t, len(actualCfg.Username) > 0)
assert.True(t, len(actualCfg.Password) > 0)
assert.Equal(t, expectedCfg.Username, actualCfg.Username)
assert.Equal(t, expectedCfg.Password, actualCfg.Password)
}

View File

@ -0,0 +1,23 @@
apiVersion: v1
clusters:
- cluster:
server: https://some-server
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: aws
name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
command: heptio-authenticator-aws
args:
- "token"
- "-i"
- "eks-cf"

View File

@ -0,0 +1,23 @@
apiVersion: v1
clusters:
- cluster:
server: https://some-server
name: gke_sample
contexts:
- context:
cluster: gke_sample
user: gke_sample
name: gke_sample
current-context: gke_sample
kind: Config
preferences: {}
users:
- name: gke_sample
user:
auth-provider:
config:
cmd-args: config config-helper --format=json
cmd-path: /google/google-cloud-sdk/bin/gcloud
expiry-key: '{.credential.token_expiry}'
token-key: '{.credential.access_token}'
name: gcp

View File

@ -0,0 +1,20 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: dGhlLWNh
server: https://someserver
name: test-cluster
contexts:
- context:
cluster: test-cluster
user: test-user
namespace: zoinx
name: test
current-context: test
kind: Config
preferences: {}
users:
- name: test-user
user:
username: admin
password: testpwd

View File

@ -0,0 +1,20 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: dGhlLWNh
server: https://someserver
name: test-cluster
contexts:
- context:
cluster: test-cluster
user: test-user
namespace: zoinx
name: test
current-context: test
kind: Config
preferences: {}
users:
- name: test-user
user:
client-certificate-data: dGhlLWNlcnQ=
client-key-data: dGhlLWtleQ==

View File

@ -1,4 +1,4 @@
package kubernetes
package context
import (
"os"
@ -7,9 +7,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/context"
"github.com/docker/cli/cli/context/store"
api "github.com/docker/compose-on-kubernetes/api"
"github.com/docker/docker/pkg/homedir"
"github.com/pkg/errors"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
@ -88,23 +86,18 @@ func (c *Endpoint) KubernetesConfig() clientcmd.ClientConfig {
// ResolveDefault returns endpoint metadata for the default Kubernetes
// endpoint, which is derived from the env-based kubeconfig.
func (c *EndpointMeta) ResolveDefault(stackOrchestrator command.Orchestrator) (interface{}, *store.EndpointTLSData, error) {
func (c *EndpointMeta) ResolveDefault() (interface{}, *store.EndpointTLSData, error) {
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" {
kubeconfig = filepath.Join(homedir.Get(), ".kube/config")
}
kubeEP, err := FromKubeConfig(kubeconfig, "", "")
if err != nil {
if stackOrchestrator == command.OrchestratorKubernetes || stackOrchestrator == command.OrchestratorAll {
return nil, nil, errors.Wrapf(err, "default orchestrator is %s but unable to resolve kubernetes endpoint", stackOrchestrator)
}
// We deliberately quash the error here, returning nil
// for the first argument is sufficient to indicate we weren't able to
// provide a default
return nil, nil, nil
}
var tls *store.EndpointTLSData
if kubeEP.TLSData != nil {
tls = kubeEP.TLSData.ToStoreTLSData()
@ -142,5 +135,21 @@ func ConfigFromContext(name string, s store.Reader) (clientcmd.ClientConfig, err
return ep.KubernetesConfig(), nil
}
// context has no kubernetes endpoint
return api.NewKubernetesConfig(""), nil
return NewKubernetesConfig(""), nil
}
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration
// file based on the KUBECONFIG environment variable and command line flags.
func NewKubernetesConfig(configPath string) clientcmd.ClientConfig {
kubeConfig := configPath
if kubeConfig == "" {
if config := os.Getenv("KUBECONFIG"); config != "" {
kubeConfig = config
} else {
kubeConfig = filepath.Join(homedir.Get(), ".kube/config")
}
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfig},
&clientcmd.ConfigOverrides{})
}

View File

@ -0,0 +1,23 @@
package context
import (
"os"
"testing"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/config/configfile"
cliflags "github.com/docker/cli/cli/flags"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDefaultContextInitializer(t *testing.T) {
cli, err := command.NewDockerCli()
require.NoError(t, err)
os.Setenv("KUBECONFIG", "./fixtures/test-kubeconfig")
defer os.Unsetenv("KUBECONFIG")
ctx, err := command.ResolveDefaultContext(&cliflags.CommonOptions{}, &configfile.ConfigFile{}, command.DefaultContextStoreConfig(), cli.Err())
require.NoError(t, err)
assert.Equal(t, "default", ctx.Meta.Name)
assert.Equal(t, "zoinx", ctx.Meta.Endpoints[KubernetesEndpoint].(EndpointMeta).DefaultNamespace)
}

View File

@ -1,4 +1,4 @@
package kubernetes
package context
import (
"io/ioutil"

3
go.mod
View File

@ -13,7 +13,6 @@ require (
github.com/containerd/containerd v1.6.0
github.com/docker/cli v20.10.12+incompatible
github.com/docker/cli-docs-tool v0.4.0
github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496 // indirect
github.com/docker/distribution v2.8.0+incompatible
github.com/docker/docker v20.10.7+incompatible
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
@ -57,7 +56,7 @@ require (
)
replace (
github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
github.com/docker/cli => github.com/docker/cli v20.10.3-0.20220226190722-8667ccd1124c+incompatible
github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220121014307-40bb9831756f+incompatible
k8s.io/api => k8s.io/api v0.22.4
k8s.io/apimachinery => k8s.io/apimachinery v0.22.4

6
go.sum
View File

@ -443,12 +443,10 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e h1:n81KvOMrLZa+VWHwST7dun9f0G98X3zREHS1ztYzZKU=
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mod h1:xpWTC2KnJMiDLkoawhsPQcXjvwATEBcbq0xevG2YR9M=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible h1:CaaxCD/l9Dxogu6lxf7AQautlv3sHULrasPadayp0fM=
github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v20.10.3-0.20220226190722-8667ccd1124c+incompatible h1:0Kr33P67t7g42iFMU3uzizk+bek+a5MThEqmt4bqVGM=
github.com/docker/cli v20.10.3-0.20220226190722-8667ccd1124c+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.4.0 h1:MdfKoErGEbFqIxQ8an9BsZ+YzKUGd58RBVkV+Q82GPo=
github.com/docker/cli-docs-tool v0.4.0/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY=
github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496 h1:90ytrX1dbzL7Uf/hHiuWwvywC+gikHv4hkAy4CwRTbs=
github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496/go.mod h1:iT2pYfi580XlpaV4KmK0T6+4/9+XoKmk/fhoDod1emE=
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=

View File

@ -1,7 +1,6 @@
package manager
import (
"io/ioutil"
"os"
"path/filepath"
"sort"
@ -57,12 +56,12 @@ func getPluginDirs(dockerCli command.Cli) ([]string, error) {
}
func addPluginCandidatesFromDir(res map[string][]string, d string) error {
dentries, err := ioutil.ReadDir(d)
dentries, err := os.ReadDir(d)
if err != nil {
return err
}
for _, dentry := range dentries {
switch dentry.Mode() & os.ModeType {
switch dentry.Type() & os.ModeType {
case 0, os.ModeSymlink:
// Regular file or symlink, keep going
default:
@ -104,6 +103,36 @@ func listPluginCandidates(dirs []string) (map[string][]string, error) {
return result, nil
}
// GetPlugin returns a plugin on the system by its name
func GetPlugin(name string, dockerCli command.Cli, rootcmd *cobra.Command) (*Plugin, error) {
pluginDirs, err := getPluginDirs(dockerCli)
if err != nil {
return nil, err
}
candidates, err := listPluginCandidates(pluginDirs)
if err != nil {
return nil, err
}
if paths, ok := candidates[name]; ok {
if len(paths) == 0 {
return nil, errPluginNotFound(name)
}
c := &candidate{paths[0]}
p, err := newPlugin(c, rootcmd)
if err != nil {
return nil, err
}
if !IsNotFound(p.Err) {
p.ShadowedPaths = paths[1:]
}
return &p, nil
}
return nil, errPluginNotFound(name)
}
// ListPlugins produces a list of the plugins available on the system
func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error) {
pluginDirs, err := getPluginDirs(dockerCli)

View File

@ -160,3 +160,11 @@ func newMetadataSubcommand(plugin *cobra.Command, meta manager.Metadata) *cobra.
}
return cmd
}
// RunningStandalone tells a CLI plugin it is run standalone by direct execution
func RunningStandalone() bool {
if os.Getenv(manager.ReexecEnvvar) != "" {
return false
}
return len(os.Args) < 2 || os.Args[1] != manager.MetadataSubcommandName
}

View File

@ -58,11 +58,8 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
// SetupRootCommand sets default usage, help, and error handling for the
// root command.
func SetupRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
opts, flags, helpCmd := setupCommonRootCommand(rootCmd)
rootCmd.SetVersionTemplate("Docker version {{.Version}}\n")
return opts, flags, helpCmd
return setupCommonRootCommand(rootCmd)
}
// SetupPluginRootCommand sets default usage, help and error handling for a plugin root command.

View File

@ -3,7 +3,6 @@ package command
import (
"context"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@ -33,9 +32,7 @@ import (
"github.com/moby/term"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/theupdateframework/notary"
notaryclient "github.com/theupdateframework/notary/client"
"github.com/theupdateframework/notary/passphrase"
)
// Streams is an interface which exposes the standard input and output streams
@ -61,9 +58,9 @@ type Cli interface {
ManifestStore() manifeststore.Store
RegistryClient(bool) registryclient.RegistryClient
ContentTrustEnabled() bool
BuildKitEnabled() (bool, error)
ContextStore() store.Store
CurrentContext() string
StackOrchestrator(flagValue string) (Orchestrator, error)
DockerEndpoint() docker.Endpoint
}
@ -171,18 +168,24 @@ func (cli *DockerCli) ContentTrustEnabled() bool {
return cli.contentTrust
}
// BuildKitEnabled returns whether buildkit is enabled either through a daemon setting
// or otherwise the client-side DOCKER_BUILDKIT environment variable
func BuildKitEnabled(si ServerInfo) (bool, error) {
buildkitEnabled := si.BuildkitVersion == types.BuilderBuildKit
if buildkitEnv := os.Getenv("DOCKER_BUILDKIT"); buildkitEnv != "" {
var err error
buildkitEnabled, err = strconv.ParseBool(buildkitEnv)
// BuildKitEnabled returns buildkit is enabled or not.
func (cli *DockerCli) BuildKitEnabled() (bool, error) {
// use DOCKER_BUILDKIT env var value if set
if v, ok := os.LookupEnv("DOCKER_BUILDKIT"); ok {
enabled, err := strconv.ParseBool(v)
if err != nil {
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
}
return enabled, nil
}
return buildkitEnabled, nil
// if a builder alias is defined, we are using BuildKit
aliasMap := cli.ConfigFile().Aliases
if _, ok := aliasMap["builder"]; ok {
return true, nil
}
// otherwise, assume BuildKit is enabled but
// not if wcow reported from server side
return cli.ServerInfo().OSType != "windows", nil
}
// ManifestStore returns a store for local manifests
@ -252,14 +255,6 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize
if cli.client == nil {
cli.client, err = newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile)
if tlsconfig.IsErrEncryptedKey(err) {
passRetriever := passphrase.PromptRetrieverWithInOut(cli.In(), cli.Out(), nil)
newClient := func(password string) (client.APIClient, error) {
cli.dockerEndpoint.TLSPassword = password
return newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile)
}
cli.client, err = getClientWithPassword(passRetriever, newClient)
}
if err != nil {
return err
}
@ -279,7 +274,7 @@ func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.
store := &ContextStoreWithDefault{
Store: store.New(cliconfig.ContextStoreDir(), storeConfig),
Resolver: func() (*DefaultContext, error) {
return ResolveDefaultContext(opts, configFile, storeConfig, ioutil.Discard)
return ResolveDefaultContext(opts, configFile, storeConfig, io.Discard)
},
}
contextName, err := resolveContextName(opts, configFile, store)
@ -377,20 +372,6 @@ func (cli *DockerCli) initializeFromClient() {
cli.client.NegotiateAPIVersionPing(ping)
}
func getClientWithPassword(passRetriever notary.PassRetriever, newClient func(password string) (client.APIClient, error)) (client.APIClient, error) {
for attempts := 0; ; attempts++ {
passwd, giveup, err := passRetriever("private", "encrypted TLS private", false, attempts)
if giveup || err != nil {
return nil, errors.Wrap(err, "private key is encrypted, but could not get passphrase")
}
apiclient, err := newClient(passwd)
if !tlsconfig.IsErrEncryptedKey(err) {
return apiclient, err
}
}
}
// NotaryClient provides a Notary Repository to interact with signed metadata for an image
func (cli *DockerCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
return trust.GetNotaryRepository(cli.In(), cli.Out(), UserAgent(), imgRefAndAuth.RepoInfo(), imgRefAndAuth.AuthConfig(), actions...)
@ -406,25 +387,6 @@ func (cli *DockerCli) CurrentContext() string {
return cli.currentContext
}
// StackOrchestrator resolves which stack orchestrator is in use
func (cli *DockerCli) StackOrchestrator(flagValue string) (Orchestrator, error) {
currentContext := cli.CurrentContext()
ctxRaw, err := cli.ContextStore().GetMetadata(currentContext)
if store.IsErrContextDoesNotExist(err) {
// case where the currentContext has been removed (CLI behavior is to fallback to using DOCKER_HOST based resolution)
return GetStackOrchestrator(flagValue, "", cli.ConfigFile().StackOrchestrator, cli.Err())
}
if err != nil {
return "", err
}
ctxMeta, err := GetDockerContext(ctxRaw)
if err != nil {
return "", err
}
ctxOrchestrator := string(ctxMeta.StackOrchestrator)
return GetStackOrchestrator(flagValue, ctxOrchestrator, cli.ConfigFile().StackOrchestrator, cli.Err())
}
// DockerEndpoint returns the current docker endpoint
func (cli *DockerCli) DockerEndpoint() docker.Endpoint {
return cli.dockerEndpoint

View File

@ -9,9 +9,8 @@ import (
// DockerContext is a typed representation of what we put in Context metadata
type DockerContext struct {
Description string
StackOrchestrator Orchestrator
AdditionalFields map[string]interface{}
Description string
AdditionalFields map[string]interface{}
}
// MarshalJSON implements custom JSON marshalling
@ -20,9 +19,6 @@ func (dc DockerContext) MarshalJSON() ([]byte, error) {
if dc.Description != "" {
s["Description"] = dc.Description
}
if dc.StackOrchestrator != "" {
s["StackOrchestrator"] = dc.StackOrchestrator
}
if dc.AdditionalFields != nil {
for k, v := range dc.AdditionalFields {
s[k] = v
@ -41,8 +37,6 @@ func (dc *DockerContext) UnmarshalJSON(payload []byte) error {
switch k {
case "Description":
dc.Description = v.(string)
case "StackOrchestrator":
dc.StackOrchestrator = Orchestrator(v.(string))
default:
if dc.AdditionalFields == nil {
dc.AdditionalFields = make(map[string]interface{})

View File

@ -41,23 +41,18 @@ type EndpointDefaultResolver interface {
// the lack of a default (e.g. because the config file which
// would contain it is missing). If there is no default then
// returns nil, nil, nil.
ResolveDefault(Orchestrator) (interface{}, *store.EndpointTLSData, error)
ResolveDefault() (interface{}, *store.EndpointTLSData, error)
}
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, storeconfig store.Config, stderr io.Writer) (*DefaultContext, error) {
stackOrchestrator, err := GetStackOrchestrator("", "", config.StackOrchestrator, stderr)
if err != nil {
return nil, err
}
contextTLSData := store.ContextTLSData{
Endpoints: make(map[string]store.EndpointTLSData),
}
contextMetadata := store.Metadata{
Endpoints: make(map[string]interface{}),
Metadata: DockerContext{
Description: "",
StackOrchestrator: stackOrchestrator,
Description: "",
},
Name: DefaultContextName,
}
@ -77,7 +72,7 @@ func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf
}
ep := get()
if i, ok := ep.(EndpointDefaultResolver); ok {
meta, tls, err := i.ResolveDefault(stackOrchestrator)
meta, tls, err := i.ResolveDefault()
if err != nil {
return err
}

View File

@ -1,84 +0,0 @@
package command
import (
"fmt"
"io"
"os"
)
// Orchestrator type acts as an enum describing supported orchestrators.
type Orchestrator string
const (
// OrchestratorKubernetes orchestrator
OrchestratorKubernetes = Orchestrator("kubernetes")
// OrchestratorSwarm orchestrator
OrchestratorSwarm = Orchestrator("swarm")
// OrchestratorAll orchestrator
OrchestratorAll = Orchestrator("all")
orchestratorUnset = Orchestrator("")
defaultOrchestrator = OrchestratorSwarm
envVarDockerStackOrchestrator = "DOCKER_STACK_ORCHESTRATOR"
envVarDockerOrchestrator = "DOCKER_ORCHESTRATOR"
)
// HasKubernetes returns true if defined orchestrator has Kubernetes capabilities.
func (o Orchestrator) HasKubernetes() bool {
return o == OrchestratorKubernetes || o == OrchestratorAll
}
// HasSwarm returns true if defined orchestrator has Swarm capabilities.
func (o Orchestrator) HasSwarm() bool {
return o == OrchestratorSwarm || o == OrchestratorAll
}
// HasAll returns true if defined orchestrator has both Swarm and Kubernetes capabilities.
func (o Orchestrator) HasAll() bool {
return o == OrchestratorAll
}
func normalize(value string) (Orchestrator, error) {
switch value {
case "kubernetes":
return OrchestratorKubernetes, nil
case "swarm":
return OrchestratorSwarm, nil
case "", "unset": // unset is the old value for orchestratorUnset. Keep accepting this for backward compat
return orchestratorUnset, nil
case "all":
return OrchestratorAll, nil
default:
return defaultOrchestrator, fmt.Errorf("specified orchestrator %q is invalid, please use either kubernetes, swarm or all", value)
}
}
// NormalizeOrchestrator parses an orchestrator value and checks if it is valid
func NormalizeOrchestrator(value string) (Orchestrator, error) {
return normalize(value)
}
// GetStackOrchestrator checks DOCKER_STACK_ORCHESTRATOR environment variable and configuration file
// orchestrator value and returns user defined Orchestrator.
func GetStackOrchestrator(flagValue, contextValue, globalDefault string, stderr io.Writer) (Orchestrator, error) {
// Check flag
if o, err := normalize(flagValue); o != orchestratorUnset {
return o, err
}
// Check environment variable
env := os.Getenv(envVarDockerStackOrchestrator)
if env == "" && os.Getenv(envVarDockerOrchestrator) != "" {
fmt.Fprintf(stderr, "WARNING: experimental environment variable %s is set. Please use %s instead\n", envVarDockerOrchestrator, envVarDockerStackOrchestrator)
}
if o, err := normalize(env); o != orchestratorUnset {
return o, err
}
if o, err := normalize(contextValue); o != orchestratorUnset {
return o, err
}
if o, err := normalize(globalDefault); o != orchestratorUnset {
return o, err
}
// Nothing set, use default orchestrator
return defaultOrchestrator, nil
}

View File

@ -63,17 +63,14 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
indexServer := registry.GetAuthConfigKey(index)
isDefaultRegistry := indexServer == ElectAuthServer(context.Background(), cli)
authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry)
if authConfig == nil {
authConfig = &types.AuthConfig{}
}
if err != nil {
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
}
err = ConfigureAuth(cli, "", "", authConfig, isDefaultRegistry)
err = ConfigureAuth(cli, "", "", &authConfig, isDefaultRegistry)
if err != nil {
return "", err
}
return EncodeAuthToBase64(*authConfig)
return EncodeAuthToBase64(authConfig)
}
}
@ -92,7 +89,7 @@ func ResolveAuthConfig(ctx context.Context, cli Cli, index *registrytypes.IndexI
// GetDefaultAuthConfig gets the default auth config given a serverAddress
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (*types.AuthConfig, error) {
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress)
}
@ -101,13 +98,15 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
if checkCredStore {
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
if err != nil {
return nil, err
return types.AuthConfig{
ServerAddress: serverAddress,
}, err
}
}
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
res := types.AuthConfig(authconfig)
return &res, nil
return res, nil
}
// ConfigureAuth handles prompting of user's username and password if needed

View File

@ -104,14 +104,18 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
return &configFile, err
}
// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
var printLegacyFileWarning bool
// Load reads the configuration files in the given directory, and sets up
// the auth config information and returns values.
// FIXME: use the internal golang config parser
func Load(configDir string) (*configfile.ConfigFile, error) {
printLegacyFileWarning = false
cfg, _, err := load(configDir)
return cfg, err
}
// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
// so we can remove the bool return value and collapse this back into `Load`
func load(configDir string) (*configfile.ConfigFile, bool, error) {
printLegacyFileWarning := false
if configDir == "" {
configDir = Dir()
@ -127,11 +131,11 @@ func Load(configDir string) (*configfile.ConfigFile, error) {
if err != nil {
err = errors.Wrap(err, filename)
}
return configFile, err
return configFile, printLegacyFileWarning, err
} else if !os.IsNotExist(err) {
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, errors.Wrap(err, filename)
return configFile, printLegacyFileWarning, errors.Wrap(err, filename)
}
// Can't find latest config file so check for the old one
@ -140,16 +144,16 @@ func Load(configDir string) (*configfile.ConfigFile, error) {
printLegacyFileWarning = true
defer file.Close()
if err := configFile.LegacyLoadFromReader(file); err != nil {
return configFile, errors.Wrap(err, filename)
return configFile, printLegacyFileWarning, errors.Wrap(err, filename)
}
}
return configFile, nil
return configFile, printLegacyFileWarning, nil
}
// LoadDefaultConfigFile attempts to load the default config file and returns
// an initialized ConfigFile struct if none is found.
func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
configFile, err := Load(Dir())
configFile, printLegacyFileWarning, err := load(Dir())
if err != nil {
fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
}

View File

@ -3,9 +3,7 @@ package configfile
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -46,8 +44,7 @@ type ConfigFile struct {
PruneFilters []string `json:"pruneFilters,omitempty"`
Proxies map[string]ProxyConfig `json:"proxies,omitempty"`
Experimental string `json:"experimental,omitempty"`
StackOrchestrator string `json:"stackOrchestrator,omitempty"`
Kubernetes *KubernetesConfig `json:"kubernetes,omitempty"`
StackOrchestrator string `json:"stackOrchestrator,omitempty"` // Deprecated: swarm is now the default orchestrator, and this option is ignored.
CurrentContext string `json:"currentContext,omitempty"`
CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"`
Plugins map[string]map[string]string `json:"plugins,omitempty"`
@ -60,11 +57,7 @@ type ProxyConfig struct {
HTTPSProxy string `json:"httpsProxy,omitempty"`
NoProxy string `json:"noProxy,omitempty"`
FTPProxy string `json:"ftpProxy,omitempty"`
}
// KubernetesConfig contains Kubernetes orchestrator settings
type KubernetesConfig struct {
AllNamespaces string `json:"allNamespaces,omitempty"`
AllProxy string `json:"allProxy,omitempty"`
}
// New initializes an empty configuration file for the given filename 'fn'
@ -81,7 +74,7 @@ func New(fn string) *ConfigFile {
// LegacyLoadFromReader reads the non-nested configuration data given and sets up the
// auth config information with given directory and populates the receiver object
func (configFile *ConfigFile) LegacyLoadFromReader(configData io.Reader) error {
b, err := ioutil.ReadAll(configData)
b, err := io.ReadAll(configData)
if err != nil {
return err
}
@ -119,7 +112,7 @@ func (configFile *ConfigFile) LegacyLoadFromReader(configData io.Reader) error {
// LoadFromReader reads the configuration data given and sets up the auth config
// information with given directory and populates the receiver object
func (configFile *ConfigFile) LoadFromReader(configData io.Reader) error {
if err := json.NewDecoder(configData).Decode(&configFile); err != nil && !errors.Is(err, io.EOF) {
if err := json.NewDecoder(configData).Decode(configFile); err != nil && !errors.Is(err, io.EOF) {
return err
}
var err error
@ -134,7 +127,7 @@ func (configFile *ConfigFile) LoadFromReader(configData io.Reader) error {
ac.ServerAddress = addr
configFile.AuthConfigs[addr] = ac
}
return checkKubernetesConfiguration(configFile.Kubernetes)
return nil
}
// ContainsAuth returns whether there is authentication configured
@ -194,7 +187,7 @@ func (configFile *ConfigFile) Save() (retErr error) {
if err := os.MkdirAll(dir, 0700); err != nil {
return err
}
temp, err := ioutil.TempFile(dir, filepath.Base(configFile.Filename))
temp, err := os.CreateTemp(dir, filepath.Base(configFile.Filename))
if err != nil {
return err
}
@ -244,6 +237,7 @@ func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts map[string]*
"HTTPS_PROXY": &config.HTTPSProxy,
"NO_PROXY": &config.NoProxy,
"FTP_PROXY": &config.FTPProxy,
"ALL_PROXY": &config.AllProxy,
}
m := runOpts
if m == nil {
@ -399,17 +393,3 @@ func (configFile *ConfigFile) SetPluginConfig(pluginname, option, value string)
delete(configFile.Plugins, pluginname)
}
}
func checkKubernetesConfiguration(kubeConfig *KubernetesConfig) error {
if kubeConfig == nil {
return nil
}
switch kubeConfig.AllNamespaces {
case "":
case "enabled":
case "disabled":
default:
return fmt.Errorf("invalid 'kubernetes.allNamespaces' value, should be 'enabled' or 'disabled': %s", kubeConfig.AllNamespaces)
}
return nil
}

View File

@ -4,7 +4,6 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"net"
"net/http"
"os"
@ -26,7 +25,12 @@ type EndpointMeta = context.EndpointMetaBase
// a Docker Engine endpoint, with its tls data
type Endpoint struct {
EndpointMeta
TLSData *context.TLSData
TLSData *context.TLSData
// Deprecated: Use of encrypted TLS private keys has been deprecated, and
// will be removed in a future release. Golang has deprecated support for
// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
// design (see https://go-review.googlesource.com/c/go/+/264159).
TLSPassword string
}
@ -62,16 +66,10 @@ func (c *Endpoint) tlsConfig() (*tls.Config, error) {
keyBytes := c.TLSData.Key
pemBlock, _ := pem.Decode(keyBytes)
if pemBlock == nil {
return nil, fmt.Errorf("no valid private key found")
return nil, errors.New("no valid private key found")
}
var err error
if x509.IsEncryptedPEMBlock(pemBlock) {
keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(c.TLSPassword))
if err != nil {
return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it")
}
keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes})
if x509.IsEncryptedPEMBlock(pemBlock) { //nolint: staticcheck // SA1019: x509.IsEncryptedPEMBlock is deprecated, and insecure by design
return nil, errors.New("private key is encrypted - support for encrypted private keys has been removed, see https://docs.docker.com/go/deprecated/")
}
x509cert, err := tls.X509KeyPair(c.TLSData.Cert, keyBytes)

View File

@ -12,11 +12,9 @@
// - tls/
// - <context id>/endpoint1/: directory containing TLS data for the endpoint1 in the corresponding context
//
// The context store itself has absolutely no knowledge about what a docker or a kubernetes endpoint should contain in term of metadata or TLS config.
// The context store itself has absolutely no knowledge about what a docker endpoint should contain in term of metadata or TLS config.
// Client code is responsible for generating and parsing endpoint metadata and TLS files.
// The multi-endpoints approach of this package allows to combine many different endpoints in the same "context" (e.g., the Docker CLI
// is able for a single context to define both a docker endpoint and a Kubernetes endpoint for the same cluster, and also specify which
// orchestrator to use by default when deploying a compose stack on this cluster).
// The multi-endpoints approach of this package allows to combine many different endpoints in the same "context".
//
// Context IDs are actually SHA256 hashes of the context name, and are there only to avoid dealing with special characters in context names.
package store

View File

@ -3,7 +3,6 @@ package store
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
@ -35,7 +34,7 @@ func (s *metadataStore) createOrUpdate(meta Metadata) error {
if err != nil {
return err
}
return ioutil.WriteFile(filepath.Join(contextDir, metaFile), bytes, 0644)
return os.WriteFile(filepath.Join(contextDir, metaFile), bytes, 0644)
}
func parseTypedOrMap(payload []byte, getter TypeGetter) (interface{}, error) {
@ -58,7 +57,7 @@ func parseTypedOrMap(payload []byte, getter TypeGetter) (interface{}, error) {
func (s *metadataStore) get(id contextdir) (Metadata, error) {
contextDir := s.contextDir(id)
bytes, err := ioutil.ReadFile(filepath.Join(contextDir, metaFile))
bytes, err := os.ReadFile(filepath.Join(contextDir, metaFile))
if err != nil {
return Metadata{}, convertContextDoesNotExist(err)
}
@ -117,7 +116,7 @@ func isContextDir(path string) bool {
}
func listRecursivelyMetadataDirs(root string) ([]string, error) {
fis, err := ioutil.ReadDir(root)
fis, err := os.ReadDir(root)
if err != nil {
return nil, err
}

View File

@ -9,7 +9,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"path"
"path/filepath"
@ -349,7 +348,7 @@ func importTar(name string, s Writer, reader io.Reader) error {
return errors.Wrap(err, hdr.Name)
}
if hdr.Name == metaFile {
data, err := ioutil.ReadAll(tr)
data, err := io.ReadAll(tr)
if err != nil {
return err
}
@ -362,7 +361,7 @@ func importTar(name string, s Writer, reader io.Reader) error {
}
importedMetaFile = true
} else if strings.HasPrefix(hdr.Name, "tls/") {
data, err := ioutil.ReadAll(tr)
data, err := io.ReadAll(tr)
if err != nil {
return err
}
@ -378,7 +377,7 @@ func importTar(name string, s Writer, reader io.Reader) error {
}
func importZip(name string, s Writer, reader io.Reader) error {
body, err := ioutil.ReadAll(&LimitedReader{R: reader, N: maxAllowedFileSizeToImport})
body, err := io.ReadAll(&LimitedReader{R: reader, N: maxAllowedFileSizeToImport})
if err != nil {
return err
}
@ -406,7 +405,7 @@ func importZip(name string, s Writer, reader io.Reader) error {
return err
}
data, err := ioutil.ReadAll(&LimitedReader{R: f, N: maxAllowedFileSizeToImport})
data, err := io.ReadAll(&LimitedReader{R: f, N: maxAllowedFileSizeToImport})
defer f.Close()
if err != nil {
return err
@ -424,7 +423,7 @@ func importZip(name string, s Writer, reader io.Reader) error {
if err != nil {
return err
}
data, err := ioutil.ReadAll(f)
data, err := io.ReadAll(f)
defer f.Close()
if err != nil {
return err

View File

@ -1,7 +1,6 @@
package store
import (
"io/ioutil"
"os"
"path/filepath"
)
@ -33,18 +32,18 @@ func (s *tlsStore) createOrUpdate(contextID contextdir, endpointName, filename s
if err := os.MkdirAll(epdir, 0700); err != nil {
return err
}
return ioutil.WriteFile(s.filePath(contextID, endpointName, filename), data, 0600)
return os.WriteFile(s.filePath(contextID, endpointName, filename), data, 0600)
}
func (s *tlsStore) getData(contextID contextdir, endpointName, filename string) ([]byte, error) {
data, err := ioutil.ReadFile(s.filePath(contextID, endpointName, filename))
data, err := os.ReadFile(s.filePath(contextID, endpointName, filename))
if err != nil {
return nil, convertTLSDataDoesNotExist(endpointName, filename, err)
}
return data, nil
}
func (s *tlsStore) remove(contextID contextdir, endpointName, filename string) error {
func (s *tlsStore) remove(contextID contextdir, endpointName, filename string) error { // nolint:unused
err := os.Remove(s.filePath(contextID, endpointName, filename))
if os.IsNotExist(err) {
return nil
@ -61,7 +60,7 @@ func (s *tlsStore) removeAllContextData(contextID contextdir) error {
}
func (s *tlsStore) listContextData(contextID contextdir) (map[string]EndpointFiles, error) {
epFSs, err := ioutil.ReadDir(s.contextDir(contextID))
epFSs, err := os.ReadDir(s.contextDir(contextID))
if err != nil {
if os.IsNotExist(err) {
return map[string]EndpointFiles{}, nil
@ -72,7 +71,7 @@ func (s *tlsStore) listContextData(contextID contextdir) (map[string]EndpointFil
for _, epFS := range epFSs {
if epFS.IsDir() {
epDir := s.endpointDir(contextID, epFS.Name())
fss, err := ioutil.ReadDir(epDir)
fss, err := os.ReadDir(epDir)
if err != nil {
return nil, err
}

View File

@ -1,7 +1,7 @@
package context
import (
"io/ioutil"
"os"
"github.com/docker/cli/cli/context/store"
"github.com/pkg/errors"
@ -77,17 +77,17 @@ func TLSDataFromFiles(caPath, certPath, keyPath string) (*TLSData, error) {
err error
)
if caPath != "" {
if ca, err = ioutil.ReadFile(caPath); err != nil {
if ca, err = os.ReadFile(caPath); err != nil {
return nil, err
}
}
if certPath != "" {
if cert, err = ioutil.ReadFile(certPath); err != nil {
if cert, err = os.ReadFile(certPath); err != nil {
return nil, err
}
}
if keyPath != "" {
if key, err = ioutil.ReadFile(keyPath); err != nil {
if key, err = os.ReadFile(keyPath); err != nil {
return nil, err
}
}

View File

@ -3,7 +3,6 @@ package store
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -47,7 +46,7 @@ func (s *fsStore) Get(listRef reference.Reference, manifest reference.Reference)
}
func (s *fsStore) getFromFilename(ref reference.Reference, filename string) (types.ImageManifest, error) {
bytes, err := ioutil.ReadFile(filename)
bytes, err := os.ReadFile(filename)
switch {
case os.IsNotExist(err):
return types.ImageManifest{}, newNotFoundError(ref.String())
@ -112,7 +111,7 @@ func (s *fsStore) GetList(listRef reference.Reference) ([]types.ImageManifest, e
// listManifests stored in a transaction
func (s *fsStore) listManifests(transaction string) ([]string, error) {
transactionDir := filepath.Join(s.root, makeFilesafeName(transaction))
fileInfos, err := ioutil.ReadDir(transactionDir)
fileInfos, err := os.ReadDir(transactionDir)
switch {
case os.IsNotExist(err):
return nil, nil
@ -120,7 +119,7 @@ func (s *fsStore) listManifests(transaction string) ([]string, error) {
return nil, err
}
filenames := []string{}
filenames := make([]string, 0, len(fileInfos))
for _, info := range fileInfos {
filenames = append(filenames, info.Name())
}
@ -137,7 +136,7 @@ func (s *fsStore) Save(listRef reference.Reference, manifest reference.Reference
if err != nil {
return err
}
return ioutil.WriteFile(filename, bytes, 0644)
return os.WriteFile(filename, bytes, 0644)
}
func (s *fsStore) createManifestListDirectory(transaction string) error {

View File

@ -321,17 +321,6 @@ func ValidateSysctl(val string) (string, error) {
return "", fmt.Errorf("sysctl '%s' is not whitelisted", val)
}
// ValidateProgressOutput errors out if an invalid value is passed to --progress
func ValidateProgressOutput(val string) error {
valid := []string{"auto", "plain", "tty"}
for _, s := range valid {
if s == val {
return nil
}
}
return fmt.Errorf("invalid value %q passed to --progress, valid values are: %s", val, strings.Join(valid, ", "))
}
// FilterOpt is a flag type for validating filters
type FilterOpt struct {
filter filters.Args

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,26 +0,0 @@
package apis
import (
"os"
"path/filepath"
"github.com/docker/docker/pkg/homedir"
"k8s.io/client-go/tools/clientcmd"
)
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration file based on
// the KUBECONFIG environment variable and command line flags.
func NewKubernetesConfig(configPath string) clientcmd.ClientConfig {
kubeConfig := configPath
if kubeConfig == "" {
if config := os.Getenv("KUBECONFIG"); config != "" {
kubeConfig = config
} else {
kubeConfig = filepath.Join(homedir.Get(), ".kube/config")
}
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfig},
&clientcmd.ConfigOverrides{})
}

View File

@ -1,4 +0,0 @@
//
// +domain=docker.com
package apis

8
vendor/modules.txt vendored
View File

@ -83,7 +83,7 @@ github.com/davecgh/go-spew/spew
# github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
github.com/distribution/distribution/v3/digestset
github.com/distribution/distribution/v3/reference
# github.com/docker/cli v20.10.12+incompatible => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
# github.com/docker/cli v20.10.12+incompatible => github.com/docker/cli v20.10.3-0.20220226190722-8667ccd1124c+incompatible
## explicit
github.com/docker/cli/cli
github.com/docker/cli/cli-plugins/manager
@ -98,7 +98,6 @@ github.com/docker/cli/cli/connhelper/commandconn
github.com/docker/cli/cli/connhelper/ssh
github.com/docker/cli/cli/context
github.com/docker/cli/cli/context/docker
github.com/docker/cli/cli/context/kubernetes
github.com/docker/cli/cli/context/store
github.com/docker/cli/cli/debug
github.com/docker/cli/cli/flags
@ -113,9 +112,6 @@ github.com/docker/cli/opts
## explicit
github.com/docker/cli-docs-tool
github.com/docker/cli-docs-tool/annotation
# github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496
## explicit
github.com/docker/compose-on-kubernetes/api
# github.com/docker/distribution v2.8.0+incompatible
## explicit
github.com/docker/distribution
@ -900,7 +896,7 @@ sigs.k8s.io/structured-merge-diff/v4/typed
sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
sigs.k8s.io/yaml
# github.com/docker/cli => github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible
# github.com/docker/cli => github.com/docker/cli v20.10.3-0.20220226190722-8667ccd1124c+incompatible
# github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220121014307-40bb9831756f+incompatible
# k8s.io/api => k8s.io/api v0.22.4
# k8s.io/apimachinery => k8s.io/apimachinery v0.22.4