diff --git a/vendor.conf b/vendor.conf index c8dde9595..37b41d293 100644 --- a/vendor.conf +++ b/vendor.conf @@ -42,20 +42,20 @@ github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 gotest.tools v2.3.0 github.com/google/go-cmp v0.2.0 go.etcd.io/bbolt v1.3.3 +github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 +github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f # cri dependencies -github.com/containerd/cri b213648c5bd0a1d2ee42709c10dff63fbfee3ad7 # master -github.com/containerd/go-cni 22460c018b64cf8bf4151b3ff9c4d077e6a88cbf -github.com/containernetworking/cni v0.6.0 -github.com/containernetworking/plugins v0.7.0 -github.com/davecgh/go-spew v1.1.0 +github.com/containerd/cri f1d492b0cdd14e76476ee4dd024696ce3634e501 # master +github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1 +github.com/containernetworking/cni v0.7.1 +github.com/containernetworking/plugins v0.7.6 +github.com/davecgh/go-spew v1.1.1 github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580 github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 github.com/emicklei/go-restful v2.2.1 -github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c -github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 -github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f +github.com/google/gofuzz 24818f796faf91cd76ec7bddd72458fbced7a6c1 github.com/json-iterator/go 1.1.5 github.com/modern-go/reflect2 1.0.1 github.com/modern-go/concurrent 1.0.3 @@ -63,9 +63,9 @@ github.com/opencontainers/selinux v1.2.2 github.com/seccomp/libseccomp-golang v0.9.1 github.com/tchap/go-patricia v2.2.6 golang.org/x/crypto 88737f569e3a9c7ab309cdc09a07fe7fc87233c3 -golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 +golang.org/x/oauth2 9f3314589c9a9136388751d9adae6b0ed400978a golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 -gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 +gopkg.in/inf.v0 v0.9.0 gopkg.in/yaml.v2 v2.2.1 k8s.io/api kubernetes-1.15.0 k8s.io/apimachinery kubernetes-1.15.0 diff --git a/vendor/github.com/containerd/cri/README.md b/vendor/github.com/containerd/cri/README.md index 17963ee8a..67d16536f 100644 --- a/vendor/github.com/containerd/cri/README.md +++ b/vendor/github.com/containerd/cri/README.md @@ -41,14 +41,16 @@ See [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd) **Note:** The support table above specifies the Kubernetes Version that was supported at time of release of the containerd - cri integration. -The following is the current support table for containerd CRI integration taking into account that Kubernetes only supports n-3 minor release versions and 1.10 is now end-of-life. +The following is the current support table for containerd CRI integration taking into account that Kubernetes only supports n-3 minor release versions and 1.10 and 1.11 are now end-of-life. | Containerd Version | Kubernetes Version | CRI Version | |:------------------:|:------------------:|:-----------:| -| v1.1 | 1.11+ | v1alpha2 | -| v1.2 | 1.11+ | v1alpha2 | -| HEAD | 1.11+ | v1alpha2 | +| v1.1 | 1.12+ | v1alpha2 | +| v1.2 | 1.12+ | v1alpha2 | +| HEAD | 1.12+ | v1alpha2 | +***Although not recommended, if you still plan to use containerd 1.2+ with Kubernetes +<=1.11, please be sure to set `disable_proc_mount=true`.*** ## Production Quality Cluster on GCE For a production quality cluster on GCE brought up with `kube-up.sh` refer [here](docs/kube-up.md). diff --git a/vendor/github.com/containerd/cri/cri.go b/vendor/github.com/containerd/cri/cri.go index 455ef736e..d477c1efb 100644 --- a/vendor/github.com/containerd/cri/cri.go +++ b/vendor/github.com/containerd/cri/cri.go @@ -17,10 +17,8 @@ limitations under the License. package cri import ( - "context" "flag" "path/filepath" - "time" "github.com/containerd/containerd" "github.com/containerd/containerd/api/services/containers/v1" @@ -74,8 +72,8 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) { } log.G(ctx).Infof("Start cri plugin with config %+v", c) - if err := validateConfig(ctx, &c); err != nil { - return nil, errors.Wrap(err, "invalid config") + if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil { + return nil, errors.Wrap(err, "invalid plugin config") } if err := setGLogLevel(); err != nil { @@ -111,67 +109,6 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) { return s, nil } -// validateConfig validates the given configuration. -func validateConfig(ctx context.Context, c *criconfig.Config) error { - if c.ContainerdConfig.Runtimes == nil { - c.ContainerdConfig.Runtimes = make(map[string]criconfig.Runtime) - } - - // Validation for deprecated untrusted_workload_runtime. - if c.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" { - log.G(ctx).Warning("`untrusted_workload_runtime` is deprecated, please use `untrusted` runtime in `runtimes` instead") - if _, ok := c.ContainerdConfig.Runtimes[criconfig.RuntimeUntrusted]; ok { - return errors.Errorf("conflicting definitions: configuration includes both `untrusted_workload_runtime` and `runtimes[%q]`", criconfig.RuntimeUntrusted) - } - c.ContainerdConfig.Runtimes[criconfig.RuntimeUntrusted] = c.ContainerdConfig.UntrustedWorkloadRuntime - } - - // Validation for deprecated default_runtime field. - if c.ContainerdConfig.DefaultRuntime.Type != "" { - log.G(ctx).Warning("`default_runtime` is deprecated, please use `default_runtime_name` to reference the default configuration you have defined in `runtimes`") - c.ContainerdConfig.DefaultRuntimeName = criconfig.RuntimeDefault - c.ContainerdConfig.Runtimes[criconfig.RuntimeDefault] = c.ContainerdConfig.DefaultRuntime - } - - // Validation for default_runtime_name - if c.ContainerdConfig.DefaultRuntimeName == "" { - return errors.New("`default_runtime_name` is empty") - } - if _, ok := c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName]; !ok { - return errors.New("no corresponding runtime configured in `runtimes` for `default_runtime_name`") - } - - // Validation for deprecated runtime options. - if c.SystemdCgroup { - if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`systemd_cgroup` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`systemd_cgroup` is deprecated, please use runtime `options` instead") - } - for _, r := range c.ContainerdConfig.Runtimes { - if r.Engine != "" { - if r.Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`runtime_engine` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`runtime_engine` is deprecated, please use runtime `options` instead") - } - if r.Root != "" { - if r.Type != plugin.RuntimeLinuxV1 { - return errors.Errorf("`runtime_root` only works for runtime %s", plugin.RuntimeLinuxV1) - } - log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead") - } - } - - // Validation for stream_idle_timeout - if c.StreamIdleTimeout != "" { - if _, err := time.ParseDuration(c.StreamIdleTimeout); err != nil { - return errors.Wrap(err, "invalid stream idle timeout") - } - } - return nil -} - // getServicesOpts get service options from plugin context. func getServicesOpts(ic *plugin.InitContext) ([]containerd.ServicesOpt, error) { plugins, err := ic.GetByType(plugin.ServicePlugin) diff --git a/vendor/github.com/containerd/cri/pkg/config/config.go b/vendor/github.com/containerd/cri/pkg/config/config.go index 54e965428..add9db694 100644 --- a/vendor/github.com/containerd/cri/pkg/config/config.go +++ b/vendor/github.com/containerd/cri/pkg/config/config.go @@ -17,8 +17,14 @@ limitations under the License. package config import ( + "context" + "time" + "github.com/BurntSushi/toml" "github.com/containerd/containerd" + "github.com/containerd/containerd/log" + "github.com/containerd/containerd/plugin" + "github.com/pkg/errors" "k8s.io/kubernetes/pkg/kubelet/server/streaming" ) @@ -41,6 +47,9 @@ type Runtime struct { // Options are config options for the runtime. If options is loaded // from toml config, it will be toml.Primitive. Options *toml.Primitive `toml:"options" json:"options"` + // PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the + // runtime spec when the container is privileged. Defaults to false. + PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices" json:"privileged_without_host_devices"` } // ContainerdConfig contains toml config related to containerd @@ -61,7 +70,6 @@ type ContainerdConfig struct { Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"` // NoPivot disables pivot-root (linux only), required when running a container in a RamDisk with runc // This only works for runtime type "io.containerd.runtime.v1.linux". - // DEPRECATED: use Runtime.Options instead. Remove when shim v1 is deprecated. NoPivot bool `toml:"no_pivot" json:"noPivot"` } @@ -93,6 +101,7 @@ type Mirror struct { // Endpoints are endpoints for a namespace. CRI plugin will try the endpoints // one by one until a working one is found. The endpoint must be a valid url // with host specified. + // The scheme, host and path from the endpoint URL will be used. Endpoints []string `toml:"endpoint" json:"endpoint"` } @@ -121,12 +130,23 @@ type TLSConfig struct { type Registry struct { // Mirrors are namespace to mirror mapping for all namespaces. Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"` + // Configs are configs for each registry. + // The key is the FDQN or IP of the registry. + Configs map[string]RegistryConfig `toml:"configs" json:"configs"` + // Auths are registry endpoint to auth config mapping. The registry endpoint must // be a valid url with host specified. + // DEPRECATED: Use Configs instead. Remove in containerd 1.4. Auths map[string]AuthConfig `toml:"auths" json:"auths"` - // TLSConfigs are pairs of CA/Cert/Key which then are used when creating the transport +} + +// RegistryConfig contains configuration used to communicate with the registry. +type RegistryConfig struct { + // Auth contains information to authenticate to the registry. + Auth *AuthConfig `toml:"auth" json:"auth"` + // TLS is a pair of CA/Cert/Key which then are used when creating the transport // that communicates with the registry. - TLSConfigs map[string]TLSConfig `toml:"tls_configs" json:"tlsConfigs"` + TLS *TLSConfig `toml:"tls" json:"tls"` } // PluginConfig contains toml config related to CRI plugin, @@ -258,3 +278,84 @@ const ( // RuntimeDefault is the implicit runtime defined for ContainerdConfig.DefaultRuntime RuntimeDefault = "default" ) + +// ValidatePluginConfig validates the given plugin configuration. +func ValidatePluginConfig(ctx context.Context, c *PluginConfig) error { + if c.ContainerdConfig.Runtimes == nil { + c.ContainerdConfig.Runtimes = make(map[string]Runtime) + } + + // Validation for deprecated untrusted_workload_runtime. + if c.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" { + log.G(ctx).Warning("`untrusted_workload_runtime` is deprecated, please use `untrusted` runtime in `runtimes` instead") + if _, ok := c.ContainerdConfig.Runtimes[RuntimeUntrusted]; ok { + return errors.Errorf("conflicting definitions: configuration includes both `untrusted_workload_runtime` and `runtimes[%q]`", RuntimeUntrusted) + } + c.ContainerdConfig.Runtimes[RuntimeUntrusted] = c.ContainerdConfig.UntrustedWorkloadRuntime + } + + // Validation for deprecated default_runtime field. + if c.ContainerdConfig.DefaultRuntime.Type != "" { + log.G(ctx).Warning("`default_runtime` is deprecated, please use `default_runtime_name` to reference the default configuration you have defined in `runtimes`") + c.ContainerdConfig.DefaultRuntimeName = RuntimeDefault + c.ContainerdConfig.Runtimes[RuntimeDefault] = c.ContainerdConfig.DefaultRuntime + } + + // Validation for default_runtime_name + if c.ContainerdConfig.DefaultRuntimeName == "" { + return errors.New("`default_runtime_name` is empty") + } + if _, ok := c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName]; !ok { + return errors.New("no corresponding runtime configured in `runtimes` for `default_runtime_name`") + } + + // Validation for deprecated runtime options. + if c.SystemdCgroup { + if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { + return errors.Errorf("`systemd_cgroup` only works for runtime %s", plugin.RuntimeLinuxV1) + } + log.G(ctx).Warning("`systemd_cgroup` is deprecated, please use runtime `options` instead") + } + if c.NoPivot { + if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { + return errors.Errorf("`no_pivot` only works for runtime %s", plugin.RuntimeLinuxV1) + } + // NoPivot can't be deprecated yet, because there is no alternative config option + // for `io.containerd.runtime.v1.linux`. + } + for _, r := range c.ContainerdConfig.Runtimes { + if r.Engine != "" { + if r.Type != plugin.RuntimeLinuxV1 { + return errors.Errorf("`runtime_engine` only works for runtime %s", plugin.RuntimeLinuxV1) + } + log.G(ctx).Warning("`runtime_engine` is deprecated, please use runtime `options` instead") + } + if r.Root != "" { + if r.Type != plugin.RuntimeLinuxV1 { + return errors.Errorf("`runtime_root` only works for runtime %s", plugin.RuntimeLinuxV1) + } + log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead") + } + } + + // Validation for deprecated auths options and mapping it to configs. + if len(c.Registry.Auths) != 0 { + if c.Registry.Configs == nil { + c.Registry.Configs = make(map[string]RegistryConfig) + } + for endpoint, auth := range c.Registry.Auths { + config := c.Registry.Configs[endpoint] + config.Auth = &auth + c.Registry.Configs[endpoint] = config + } + log.G(ctx).Warning("`auths` is deprecated, please use registry`configs` instead") + } + + // Validation for stream_idle_timeout + if c.StreamIdleTimeout != "" { + if _, err := time.ParseDuration(c.StreamIdleTimeout); err != nil { + return errors.Wrap(err, "invalid stream idle timeout") + } + } + return nil +} diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go index 7647c373c..c705fd4dc 100644 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go +++ b/vendor/github.com/containerd/cri/pkg/containerd/opts/container.go @@ -25,10 +25,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/continuity/fs" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) // WithNewSnapshot wraps `containerd.WithNewSnapshot` so that if creating the @@ -80,7 +80,7 @@ func WithVolumes(volumeMounts map[string]string) containerd.NewContainerOpts { } defer func() { if uerr := mount.Unmount(root, 0); uerr != nil { - logrus.WithError(uerr).Errorf("Failed to unmount snapshot %q", c.SnapshotKey) + log.G(ctx).WithError(uerr).Errorf("Failed to unmount snapshot %q", c.SnapshotKey) if err == nil { err = uerr } diff --git a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go b/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go index 90e5bff71..0da421a5e 100644 --- a/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go +++ b/vendor/github.com/containerd/cri/pkg/containerd/opts/spec.go @@ -27,18 +27,20 @@ import ( "strings" "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" - osinterface "github.com/containerd/cri/pkg/os" - "github.com/containerd/cri/pkg/util" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runc/libcontainer/devices" runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/sys/unix" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" + + osinterface "github.com/containerd/cri/pkg/os" + "github.com/containerd/cri/pkg/util" ) const ( @@ -250,7 +252,7 @@ func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*ru s.Linux.RootfsPropagation = "rslave" } default: - logrus.Warnf("Unknown propagation mode for hostPath %q", mount.HostPath) + log.G(ctx).Warnf("Unknown propagation mode for hostPath %q", mount.HostPath) options = append(options, "rprivate") } diff --git a/vendor/github.com/containerd/cri/pkg/log/log.go b/vendor/github.com/containerd/cri/pkg/log/log.go deleted file mode 100644 index ec1d91559..000000000 --- a/vendor/github.com/containerd/cri/pkg/log/log.go +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2018 The Containerd Authors. - -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. -*/ - -package log - -import "github.com/containerd/containerd/log" - -// Trace logs a message at level Trace on the standard logger. -func Trace(args ...interface{}) { - log.Trace(log.L, args...) -} - -// Tracef logs a message at level Trace on the standard logger. -func Tracef(format string, args ...interface{}) { - log.Tracef(log.L, format, args...) -} diff --git a/vendor/github.com/containerd/cri/pkg/server/container_attach.go b/vendor/github.com/containerd/cri/pkg/server/container_attach.go index 7a4c2c609..79aed7bb1 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_attach.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_attach.go @@ -20,8 +20,8 @@ import ( "io" "github.com/containerd/containerd" + "github.com/containerd/containerd/log" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" "k8s.io/client-go/tools/remotecommand" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -62,7 +62,7 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re } handleResizing(resize, func(size remotecommand.TerminalSize) { if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil { - logrus.WithError(err).Errorf("Failed to resize task %q console", id) + log.G(ctx).WithError(err).Errorf("Failed to resize task %q console", id) } }) diff --git a/vendor/github.com/containerd/cri/pkg/server/container_create.go b/vendor/github.com/containerd/cri/pkg/server/container_create.go index 93632bd58..d6f9779c4 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_create.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_create.go @@ -26,22 +26,22 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/contrib/apparmor" "github.com/containerd/containerd/contrib/seccomp" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/oci" - "github.com/containerd/typeurl" - "github.com/davecgh/go-spew/spew" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/annotations" + "github.com/containerd/cri/pkg/config" customopts "github.com/containerd/cri/pkg/containerd/opts" ctrdutil "github.com/containerd/cri/pkg/containerd/util" cio "github.com/containerd/cri/pkg/server/io" containerstore "github.com/containerd/cri/pkg/store/container" "github.com/containerd/cri/pkg/util" + "github.com/containerd/typeurl" + "github.com/davecgh/go-spew/spew" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" + "golang.org/x/net/context" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" ) const ( @@ -67,7 +67,7 @@ func init() { // CreateContainer creates a new container in the given PodSandbox. func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateContainerRequest) (_ *runtime.CreateContainerResponse, retErr error) { config := r.GetConfig() - logrus.Debugf("Container config %+v", config) + log.G(ctx).Debugf("Container config %+v", config) sandboxConfig := r.GetSandboxConfig() sandbox, err := c.sandboxStore.Get(r.GetPodSandboxId()) if err != nil { @@ -89,7 +89,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta return nil, errors.New("container config must include metadata") } name := makeContainerName(metadata, sandboxConfig.GetMetadata()) - logrus.Debugf("Generated id %q for container %q", id, name) + log.G(ctx).Debugf("Generated id %q for container %q", id, name) if err = c.containerNameIndex.Reserve(name, id); err != nil { return nil, errors.Wrapf(err, "failed to reserve container name %q", name) } @@ -135,7 +135,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta if retErr != nil { // Cleanup the container root directory. if err = c.os.RemoveAll(containerRootDir); err != nil { - logrus.WithError(err).Errorf("Failed to remove container root directory %q", + log.G(ctx).WithError(err).Errorf("Failed to remove container root directory %q", containerRootDir) } } @@ -149,7 +149,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta if retErr != nil { // Cleanup the volatile container root directory. if err = c.os.RemoveAll(volatileContainerRootDir); err != nil { - logrus.WithError(err).Errorf("Failed to remove volatile container root directory %q", + log.G(ctx).WithError(err).Errorf("Failed to remove volatile container root directory %q", volatileContainerRootDir) } } @@ -165,15 +165,15 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta if err != nil { return nil, errors.Wrap(err, "failed to get sandbox runtime") } - logrus.Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id) + log.G(ctx).Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id) spec, err := c.generateContainerSpec(id, sandboxID, sandboxPid, config, sandboxConfig, - &image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime.PodAnnotations) + &image.ImageSpec.Config, append(mounts, volumeMounts...), ociRuntime) if err != nil { return nil, errors.Wrapf(err, "failed to generate container %q spec", id) } - logrus.Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec)) + log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec)) // Set snapshotter before any other options. opts := []containerd.NewContainerOpts{ @@ -199,10 +199,10 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta // Validate log paths and compose full container log path. if sandboxConfig.GetLogDirectory() != "" && config.GetLogPath() != "" { meta.LogPath = filepath.Join(sandboxConfig.GetLogDirectory(), config.GetLogPath()) - logrus.Debugf("Composed container full log path %q using sandbox log dir %q and container log path %q", + log.G(ctx).Debugf("Composed container full log path %q using sandbox log dir %q and container log path %q", meta.LogPath, sandboxConfig.GetLogDirectory(), config.GetLogPath()) } else { - logrus.Infof("Logging will be disabled due to empty log paths for sandbox (%q) or container (%q)", + log.G(ctx).Infof("Logging will be disabled due to empty log paths for sandbox (%q) or container (%q)", sandboxConfig.GetLogDirectory(), config.GetLogPath()) } @@ -214,7 +214,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta defer func() { if retErr != nil { if err := containerIO.Close(); err != nil { - logrus.WithError(err).Errorf("Failed to close container io %q", id) + log.G(ctx).WithError(err).Errorf("Failed to close container io %q", id) } } }() @@ -227,11 +227,16 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta userstr, err := generateUserString( securityContext.GetRunAsUsername(), securityContext.GetRunAsUser(), - securityContext.GetRunAsGroup(), - ) + securityContext.GetRunAsGroup()) + if err != nil { return nil, errors.Wrap(err, "failed to generate user string") } + if userstr == "" { + // Lastly, since no user override was passed via CRI try to set via OCI + // Image + userstr = image.ImageSpec.Config.User + } if userstr != "" { specOpts = append(specOpts, oci.WithUser(userstr)) } @@ -286,7 +291,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta deferCtx, deferCancel := ctrdutil.DeferContext() defer deferCancel() if err := cntr.Delete(deferCtx, containerd.WithSnapshotCleanup); err != nil { - logrus.WithError(err).Errorf("Failed to delete containerd container %q", id) + log.G(ctx).WithError(err).Errorf("Failed to delete containerd container %q", id) } } }() @@ -304,7 +309,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta if retErr != nil { // Cleanup container checkpoint on error. if err := container.Delete(); err != nil { - logrus.WithError(err).Errorf("Failed to cleanup container checkpoint for %q", id) + log.G(ctx).WithError(err).Errorf("Failed to cleanup container checkpoint for %q", id) } } }() @@ -318,7 +323,8 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta } func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig, - sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount, runtimePodAnnotations []string) (*runtimespec.Spec, error) { + sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount, + ociRuntime config.Runtime) (*runtimespec.Spec, error) { specOpts := []oci.SpecOpts{ customopts.WithoutRunMount, @@ -380,7 +386,10 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() { return nil, errors.New("no privileged container allowed in sandbox") } - specOpts = append(specOpts, oci.WithPrivileged, customopts.WithPrivilegedDevices) + specOpts = append(specOpts, oci.WithPrivileged) + if !ociRuntime.PrivilegedWithoutHostDevices { + specOpts = append(specOpts, customopts.WithPrivilegedDevices) + } } else { // not privileged specOpts = append(specOpts, customopts.WithDevices(c.os, config), customopts.WithCapabilities(securityContext)) } @@ -408,8 +417,7 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP } else { specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources())) if sandboxConfig.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id, - c.config.SystemdCgroup) + cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id) specOpts = append(specOpts, oci.WithCgroup(cgroupsPath)) } } @@ -417,7 +425,7 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP supplementalGroups := securityContext.GetSupplementalGroups() for pKey, pValue := range getPassthroughAnnotations(sandboxConfig.Annotations, - runtimePodAnnotations) { + ociRuntime.PodAnnotations) { specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) } @@ -590,7 +598,20 @@ func generateApparmorSpecOpts(apparmorProf string, privileged, apparmorEnabled b } } -// generateUserString generates valid user string based on OCI Image Spec v1.0.0. +// generateUserString generates valid user string based on OCI Image Spec +// v1.0.0. +// +// CRI defines that the following combinations are valid: +// +// (none) -> "" +// username -> username +// username, uid -> username +// username, uid, gid -> username:gid +// username, gid -> username:gid +// uid -> uid +// uid, gid -> uid:gid +// gid -> error +// // TODO(random-liu): Add group name support in CRI. func generateUserString(username string, uid, gid *runtime.Int64Value) (string, error) { var userstr, groupstr string diff --git a/vendor/github.com/containerd/cri/pkg/server/container_execsync.go b/vendor/github.com/containerd/cri/pkg/server/container_execsync.go index 516b44e4a..b46e6e562 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_execsync.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_execsync.go @@ -25,9 +25,9 @@ import ( "github.com/containerd/containerd" containerdio "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/oci" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" "k8s.io/client-go/tools/remotecommand" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -104,7 +104,7 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp pspec.Terminal = opts.tty if opts.tty { - if err := oci.WithEnv([]string{"TERM=xterm"})(nil, nil, nil, spec); err != nil { + if err := oci.WithEnv([]string{"TERM=xterm"})(ctx, nil, nil, spec); err != nil { return nil, errors.Wrap(err, "add TERM env var to spec") } } @@ -118,7 +118,7 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp opts.stderr = cio.NewDiscardLogger() } execID := util.GenerateID() - logrus.Debugf("Generated exec id %q for container %q", execID, id) + log.G(ctx).Debugf("Generated exec id %q for container %q", execID, id) volatileRootDir := c.getVolatileContainerRootDir(id) var execIO *cio.ExecIO process, err := task.Exec(ctx, execID, pspec, @@ -135,7 +135,7 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp deferCtx, deferCancel := ctrdutil.DeferContext() defer deferCancel() if _, err := process.Delete(deferCtx, containerd.WithProcessKill); err != nil { - logrus.WithError(err).Errorf("Failed to delete exec process %q for container %q", execID, id) + log.G(ctx).WithError(err).Errorf("Failed to delete exec process %q for container %q", execID, id) } }() @@ -149,7 +149,7 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp handleResizing(opts.resize, func(size remotecommand.TerminalSize) { if err := process.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil { - logrus.WithError(err).Errorf("Failed to resize process %q console for container %q", execID, id) + log.G(ctx).WithError(err).Errorf("Failed to resize process %q console for container %q", execID, id) } }) @@ -179,19 +179,19 @@ func (c *criService) execInContainer(ctx context.Context, id string, opts execOp } // Wait for the process to be killed. exitRes := <-exitCh - logrus.Infof("Timeout received while waiting for exec process kill %q code %d and error %v", + log.G(ctx).Infof("Timeout received while waiting for exec process kill %q code %d and error %v", execID, exitRes.ExitCode(), exitRes.Error()) <-attachDone - logrus.Debugf("Stream pipe for exec process %q done", execID) + log.G(ctx).Debugf("Stream pipe for exec process %q done", execID) return nil, errors.Wrapf(execCtx.Err(), "timeout %v exceeded", opts.timeout) case exitRes := <-exitCh: code, _, err := exitRes.Result() - logrus.Infof("Exec process %q exits with exit code %d and error %v", execID, code, err) + log.G(ctx).Infof("Exec process %q exits with exit code %d and error %v", execID, code, err) if err != nil { return nil, errors.Wrapf(err, "failed while waiting for exec %q", execID) } <-attachDone - logrus.Debugf("Stream pipe for exec process %q done", execID) + log.G(ctx).Debugf("Stream pipe for exec process %q done", execID) return &code, nil } } diff --git a/vendor/github.com/containerd/cri/pkg/server/container_remove.go b/vendor/github.com/containerd/cri/pkg/server/container_remove.go index 295faaf43..e5d9ef2d0 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_remove.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_remove.go @@ -19,13 +19,12 @@ package server import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/docker/docker/pkg/system" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/log" "github.com/containerd/cri/pkg/store" containerstore "github.com/containerd/cri/pkg/store/container" ) @@ -39,7 +38,7 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta return nil, errors.Wrapf(err, "an error occurred when try to find container %q", r.GetContainerId()) } // Do not return error if container metadata doesn't exist. - log.Tracef("RemoveContainer called for container %q that does not exist", r.GetContainerId()) + log.G(ctx).Tracef("RemoveContainer called for container %q that does not exist", r.GetContainerId()) return &runtime.RemoveContainerResponse{}, nil } id := container.ID @@ -53,7 +52,7 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta if retErr != nil { // Reset removing if remove failed. if err := resetContainerRemoving(container); err != nil { - logrus.WithError(err).Errorf("failed to reset removing state for container %q", id) + log.G(ctx).WithError(err).Errorf("failed to reset removing state for container %q", id) } } }() @@ -68,7 +67,7 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta if !errdefs.IsNotFound(err) { return nil, errors.Wrapf(err, "failed to delete containerd container %q", id) } - log.Tracef("Remove called for containerd container %q that does not exist", id) + log.G(ctx).Tracef("Remove called for containerd container %q that does not exist", id) } // Delete container checkpoint. diff --git a/vendor/github.com/containerd/cri/pkg/server/container_start.go b/vendor/github.com/containerd/cri/pkg/server/container_start.go index 79922f6dd..402a77ae5 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_start.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_start.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd" containerdio "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/plugin" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -65,11 +66,11 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain status.Message = retErr.Error() return status, nil }); err != nil { - logrus.WithError(err).Errorf("failed to set start failure state for container %q", id) + log.G(ctx).WithError(err).Errorf("failed to set start failure state for container %q", id) } } if err := resetContainerStarting(cntr); err != nil { - logrus.WithError(err).Errorf("failed to reset starting state for container %q", id) + log.G(ctx).WithError(err).Errorf("failed to reset starting state for container %q", id) } }() @@ -113,7 +114,7 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain defer deferCancel() // It's possible that task is deleted by event monitor. if _, err := task.Delete(deferCtx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Errorf("Failed to delete containerd task %q", id) + log.G(ctx).WithError(err).Errorf("Failed to delete containerd task %q", id) } } }() diff --git a/vendor/github.com/containerd/cri/pkg/server/container_stop.go b/vendor/github.com/containerd/cri/pkg/server/container_stop.go index 0b4f97e5e..633cbb56a 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_stop.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_stop.go @@ -23,8 +23,8 @@ import ( "github.com/containerd/containerd" eventtypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -57,7 +57,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore state := container.Status.Get().State() if state != runtime.ContainerState_CONTAINER_RUNNING && state != runtime.ContainerState_CONTAINER_UNKNOWN { - logrus.Infof("Container to stop %q must be in running or unknown state, current state %q", + log.G(ctx).Infof("Container to stop %q must be in running or unknown state, current state %q", id, criContainerStateToString(state)) return nil } @@ -118,7 +118,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore if err != store.ErrNotExist { return errors.Wrapf(err, "failed to get image %q", container.ImageRef) } - logrus.Warningf("Image %q not found, stop container with signal %q", container.ImageRef, stopSignal) + log.G(ctx).Warningf("Image %q not found, stop container with signal %q", container.ImageRef, stopSignal) } else { if image.ImageSpec.Config.StopSignal != "" { stopSignal = image.ImageSpec.Config.StopSignal @@ -129,7 +129,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore if err != nil { return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal) } - logrus.Infof("Stop container %q with signal %v", id, sig) + log.G(ctx).Infof("Stop container %q with signal %v", id, sig) if err = task.Kill(ctx, sig); err != nil && !errdefs.IsNotFound(err) { return errors.Wrapf(err, "failed to stop container %q", id) } @@ -146,10 +146,10 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore return ctx.Err() } // sigTermCtx was exceeded. Send SIGKILL - logrus.Debugf("Stop container %q with signal %v timed out", id, sig) + log.G(ctx).Debugf("Stop container %q with signal %v timed out", id, sig) } - logrus.Infof("Kill container %q", id) + log.G(ctx).Infof("Kill container %q", id) if err = task.Kill(ctx, syscall.SIGKILL); err != nil && !errdefs.IsNotFound(err) { return errors.Wrapf(err, "failed to kill container %q", id) } diff --git a/vendor/github.com/containerd/cri/pkg/server/container_update_resources.go b/vendor/github.com/containerd/cri/pkg/server/container_update_resources.go index faa1e4d94..2c9d03389 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_update_resources.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_update_resources.go @@ -22,10 +22,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/typeurl" runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -70,7 +70,7 @@ func (c *criService) updateContainerResources(ctx context.Context, if err != nil { return errors.Wrap(err, "failed to get container spec") } - newSpec, err := updateOCILinuxResource(oldSpec, resources) + newSpec, err := updateOCILinuxResource(ctx, oldSpec, resources) if err != nil { return errors.Wrap(err, "failed to update resource in spec") } @@ -84,7 +84,7 @@ func (c *criService) updateContainerResources(ctx context.Context, defer deferCancel() // Reset spec on error. if err := updateContainerSpec(deferCtx, cntr.Container, oldSpec); err != nil { - logrus.WithError(err).Errorf("Failed to update spec %+v for container %q", oldSpec, id) + log.G(ctx).WithError(err).Errorf("Failed to update spec %+v for container %q", oldSpec, id) } } }() @@ -130,7 +130,7 @@ func updateContainerSpec(ctx context.Context, cntr containerd.Container, spec *r } // updateOCILinuxResource updates container resource limit. -func updateOCILinuxResource(spec *runtimespec.Spec, new *runtime.LinuxContainerResources) (*runtimespec.Spec, error) { +func updateOCILinuxResource(ctx context.Context, spec *runtimespec.Spec, new *runtime.LinuxContainerResources) (*runtimespec.Spec, error) { // Copy to make sure old spec is not changed. var cloned runtimespec.Spec if err := util.DeepCopy(&cloned, spec); err != nil { @@ -139,7 +139,7 @@ func updateOCILinuxResource(spec *runtimespec.Spec, new *runtime.LinuxContainerR if cloned.Linux == nil { cloned.Linux = &runtimespec.Linux{} } - if err := opts.WithResources(new)(nil, nil, nil, &cloned); err != nil { + if err := opts.WithResources(new)(ctx, nil, nil, &cloned); err != nil { return nil, errors.Wrap(err, "unable to set linux container resources") } return &cloned, nil diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers.go b/vendor/github.com/containerd/cri/pkg/server/helpers.go index 6890415d8..1d1565704 100644 --- a/vendor/github.com/containerd/cri/pkg/server/helpers.go +++ b/vendor/github.com/containerd/cri/pkg/server/helpers.go @@ -142,12 +142,12 @@ func makeContainerName(c *runtime.ContainerMetadata, s *runtime.PodSandboxMetada } // getCgroupsPath generates container cgroups path. -func getCgroupsPath(cgroupsParent, id string, systemdCgroup bool) string { - if systemdCgroup { - // Convert a.slice/b.slice/c.slice to c.slice. - p := path.Base(cgroupsParent) +func getCgroupsPath(cgroupsParent, id string) string { + base := path.Base(cgroupsParent) + if strings.HasSuffix(base, ".slice") { + // For a.slice/b.slice/c.slice, base is c.slice. // runc systemd cgroup path format is "slice:prefix:name". - return strings.Join([]string{p, "cri-containerd", id}, ":") + return strings.Join([]string{base, "cri-containerd", id}, ":") } return filepath.Join(cgroupsParent, id) } diff --git a/vendor/github.com/containerd/cri/pkg/server/image_pull.go b/vendor/github.com/containerd/cri/pkg/server/image_pull.go index 019c45dcb..daa388481 100644 --- a/vendor/github.com/containerd/cri/pkg/server/image_pull.go +++ b/vendor/github.com/containerd/cri/pkg/server/image_pull.go @@ -30,16 +30,15 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" containerdimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/cri/pkg/config" distribution "github.com/docker/distribution/reference" imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" + + criconfig "github.com/containerd/cri/pkg/config" ) // For image management: @@ -92,16 +91,21 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) } ref := namedRef.String() if ref != imageRef { - logrus.Debugf("PullImage using normalized image ref: %q", ref) + log.G(ctx).Debugf("PullImage using normalized image ref: %q", ref) } - resolver, desc, err := c.getResolver(ctx, ref, c.credentials(r.GetAuth())) - if err != nil { - return nil, errors.Wrapf(err, "failed to resolve image %q", ref) - } - // We have to check schema1 here, because after `Pull`, schema1 - // image has already been converted. - isSchema1 := desc.MediaType == containerdimages.MediaTypeDockerSchema1Manifest - + var ( + resolver = docker.NewResolver(docker.ResolverOptions{ + Hosts: c.registryHosts(r.GetAuth()), + }) + isSchema1 bool + imageHandler containerdimages.HandlerFunc = func(_ context.Context, + desc imagespec.Descriptor) ([]imagespec.Descriptor, error) { + if desc.MediaType == containerdimages.MediaTypeDockerSchema1Manifest { + isSchema1 = true + } + return nil, nil + } + ) image, err := c.client.Pull(ctx, ref, containerd.WithSchema1Conversion, containerd.WithResolver(resolver), @@ -109,6 +113,7 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) containerd.WithPullUnpack, containerd.WithPullLabel(imageLabelKey, imageLabelValue), containerd.WithMaxConcurrentDownloads(c.config.MaxConcurrentDownloads), + containerd.WithImageHandler(imageHandler), ) if err != nil { return nil, errors.Wrapf(err, "failed to pull and unpack image %q", ref) @@ -136,7 +141,7 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) } } - logrus.Debugf("Pulled image %q with image id %q, repo tag %q, repo digest %q", imageRef, imageID, + log.G(ctx).Debugf("Pulled image %q with image id %q, repo tag %q, repo digest %q", imageRef, imageID, repoTag, repoDigest) // NOTE(random-liu): the actual state in containerd is the source of truth, even we maintain // in-memory image store, it's only for in-memory indexing. The image could be removed @@ -147,10 +152,20 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest) } // ParseAuth parses AuthConfig and returns username and password/secret required by containerd. -func ParseAuth(auth *runtime.AuthConfig) (string, string, error) { +func ParseAuth(auth *runtime.AuthConfig, host string) (string, string, error) { if auth == nil { return "", "", nil } + if auth.ServerAddress != "" { + // Do not return the auth info when server address doesn't match. + u, err := url.Parse(auth.ServerAddress) + if err != nil { + return "", "", errors.Wrap(err, "parse server address") + } + if host != u.Host { + return "", "", nil + } + } if auth.Username != "" { return auth.Username, auth.Password, nil } @@ -234,31 +249,23 @@ func (c *criService) updateImage(ctx context.Context, r string) error { return nil } -// credentials returns a credential function for docker resolver to use. -func (c *criService) credentials(auth *runtime.AuthConfig) func(string) (string, string, error) { - return func(host string) (string, string, error) { - if auth == nil { - // Get default auth from config. - for h, ac := range c.config.Registry.Auths { - u, err := url.Parse(h) - if err != nil { - return "", "", errors.Wrapf(err, "parse auth host %q", h) - } - if u.Host == host { - auth = toRuntimeAuthConfig(ac) - break - } - } - } - return ParseAuth(auth) - } -} - // getTLSConfig returns a TLSConfig configured with a CA/Cert/Key specified by registryTLSConfig -func (c *criService) getTLSConfig(registryTLSConfig config.TLSConfig) (*tls.Config, error) { - cert, err := tls.LoadX509KeyPair(registryTLSConfig.CertFile, registryTLSConfig.KeyFile) - if err != nil { - return nil, errors.Wrap(err, "failed to load cert file") +func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.Config, error) { + var ( + cert tls.Certificate + err error + ) + if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile != "" { + cert, err = tls.LoadX509KeyPair(registryTLSConfig.CertFile, registryTLSConfig.KeyFile) + if err != nil { + return nil, errors.Wrap(err, "failed to load cert file") + } + } + if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile == "" { + return nil, errors.Errorf("cert file %q was specified, but no corresponding key file was specified", registryTLSConfig.CertFile) + } + if registryTLSConfig.CertFile == "" && registryTLSConfig.KeyFile != "" { + return nil, errors.Errorf("key file %q was specified, but no corresponding cert file was specified", registryTLSConfig.KeyFile) } caCertPool, err := x509.SystemCertPool() @@ -272,75 +279,98 @@ func (c *criService) getTLSConfig(registryTLSConfig config.TLSConfig) (*tls.Conf caCertPool.AppendCertsFromPEM(caCert) tlsConfig := &tls.Config{ - Certificates: []tls.Certificate{cert}, - RootCAs: caCertPool, + RootCAs: caCertPool, + } + if len(cert.Certificate) != 0 { + tlsConfig.Certificates = []tls.Certificate{cert} } tlsConfig.BuildNameToCertificate() return tlsConfig, nil } -// getResolver tries registry mirrors and the default registry, and returns the resolver and descriptor -// from the first working registry. -func (c *criService) getResolver(ctx context.Context, ref string, cred func(string) (string, string, error)) (remotes.Resolver, imagespec.Descriptor, error) { - refspec, err := reference.Parse(ref) - if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrap(err, "parse image reference") +// registryHosts is the registry hosts to be used by the resolver. +func (c *criService) registryHosts(auth *runtime.AuthConfig) docker.RegistryHosts { + return func(host string) ([]docker.RegistryHost, error) { + var registries []docker.RegistryHost + + endpoints, err := c.registryEndpoints(host) + if err != nil { + return nil, errors.Wrap(err, "get registry endpoints") + } + for _, e := range endpoints { + u, err := url.Parse(e) + if err != nil { + return nil, errors.Wrapf(err, "parse registry endpoint %q from mirrors", e) + } + + var ( + transport = newTransport() + client = &http.Client{Transport: transport} + config = c.config.Registry.Configs[u.Host] + ) + + if u.Scheme != "https" && config.TLS != nil { + return nil, errors.Errorf("tls provided for http endpoint %q", e) + } + + if config.TLS != nil { + transport.TLSClientConfig, err = c.getTLSConfig(*config.TLS) + if err != nil { + return nil, errors.Wrapf(err, "get TLSConfig for registry %q", e) + } + } + + if auth == nil && config.Auth != nil { + auth = toRuntimeAuthConfig(*config.Auth) + } + + if u.Path == "" { + u.Path = "/v2" + } + + registries = append(registries, docker.RegistryHost{ + Client: client, + Authorizer: docker.NewDockerAuthorizer( + docker.WithAuthClient(client), + docker.WithAuthCreds(func(host string) (string, string, error) { + return ParseAuth(auth, host) + })), + Host: u.Host, + Scheme: u.Scheme, + Path: u.Path, + Capabilities: docker.HostCapabilityResolve | docker.HostCapabilityPull, + }) + } + return registries, nil } +} - var ( - transport = newTransport() - httpClient = &http.Client{Transport: transport} - ) - - // Try mirrors in order first, and then try default host name. - for _, e := range c.config.Registry.Mirrors[refspec.Hostname()].Endpoints { +// registryEndpoints returns endpoints for a given host. +// It adds default registry endpoint if it does not exist in the passed-in endpoint list. +// It also supports wildcard host matching with `*`. +func (c *criService) registryEndpoints(host string) ([]string, error) { + var endpoints []string + _, ok := c.config.Registry.Mirrors[host] + if ok { + endpoints = c.config.Registry.Mirrors[host].Endpoints + } else { + endpoints = c.config.Registry.Mirrors["*"].Endpoints + } + defaultHost, err := docker.DefaultHost(host) + if err != nil { + return nil, errors.Wrap(err, "get default host") + } + for _, e := range endpoints { u, err := url.Parse(e) if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrapf(err, "parse registry endpoint %q", e) + return nil, errors.Wrap(err, "parse endpoint url") } - - if registryTLSConfig, ok := c.config.Registry.TLSConfigs[u.Host]; ok { - transport.TLSClientConfig, err = c.getTLSConfig(registryTLSConfig) - if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrapf(err, "get TLSConfig for registry %q", refspec.Hostname()) - } - } - - resolver := docker.NewResolver(docker.ResolverOptions{ - Authorizer: docker.NewAuthorizer(httpClient, cred), - Client: httpClient, - Host: func(string) (string, error) { return u.Host, nil }, - // By default use "https". - PlainHTTP: u.Scheme == "http", - }) - _, desc, err := resolver.Resolve(ctx, ref) - if err == nil { - return resolver, desc, nil - } - logrus.WithError(err).Debugf("Tried registry mirror %q but failed", e) - // Continue to try next endpoint - } - - hostname, err := docker.DefaultHost(refspec.Hostname()) - if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrapf(err, "get host for refspec %q", refspec.Hostname()) - } - if registryTLSConfig, ok := c.config.Registry.TLSConfigs[hostname]; ok { - transport.TLSClientConfig, err = c.getTLSConfig(registryTLSConfig) - if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrapf(err, "get TLSConfig for registry %q", refspec.Hostname()) + if u.Host == host { + // Do not add default if the endpoint already exists. + return endpoints, nil } } - - resolver := docker.NewResolver(docker.ResolverOptions{ - Credentials: cred, - Client: httpClient, - }) - _, desc, err := resolver.Resolve(ctx, ref) - if err != nil { - return nil, imagespec.Descriptor{}, errors.Wrap(err, "no available registry endpoint") - } - return resolver, desc, nil + return append(endpoints, "https://"+defaultHost), nil } // newTransport returns a new HTTP transport used to pull image. diff --git a/vendor/github.com/containerd/cri/pkg/server/image_status.go b/vendor/github.com/containerd/cri/pkg/server/image_status.go index 657b127b9..f03739d9a 100644 --- a/vendor/github.com/containerd/cri/pkg/server/image_status.go +++ b/vendor/github.com/containerd/cri/pkg/server/image_status.go @@ -19,14 +19,14 @@ package server import ( "encoding/json" + "github.com/containerd/containerd/log" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" "github.com/containerd/cri/pkg/store" imagestore "github.com/containerd/cri/pkg/store/image" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) // ImageStatus returns the status of the image, returns nil if the image isn't present. @@ -97,7 +97,7 @@ func (c *criService) toCRIImageInfo(ctx context.Context, image *imagestore.Image if err == nil { info["info"] = string(m) } else { - logrus.WithError(err).Errorf("failed to marshal info %v", imi) + log.G(ctx).WithError(err).Errorf("failed to marshal info %v", imi) info["info"] = err.Error() } diff --git a/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go b/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go index aeebb9056..8a23c1393 100644 --- a/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go +++ b/vendor/github.com/containerd/cri/pkg/server/instrumented_service.go @@ -19,13 +19,12 @@ package server import ( "errors" - "github.com/sirupsen/logrus" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/containerd/errdefs" ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/log" ) // instrumentedService wraps service with containerd namespace and logs. @@ -52,12 +51,12 @@ func (in *instrumentedService) RunPodSandbox(ctx context.Context, r *runtime.Run if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("RunPodsandbox for %+v", r.GetConfig().GetMetadata()) + log.G(ctx).Infof("RunPodsandbox for %+v", r.GetConfig().GetMetadata()) defer func() { if err != nil { - logrus.WithError(err).Errorf("RunPodSandbox for %+v failed, error", r.GetConfig().GetMetadata()) + log.G(ctx).WithError(err).Errorf("RunPodSandbox for %+v failed, error", r.GetConfig().GetMetadata()) } else { - logrus.Infof("RunPodSandbox for %+v returns sandbox id %q", r.GetConfig().GetMetadata(), res.GetPodSandboxId()) + log.G(ctx).Infof("RunPodSandbox for %+v returns sandbox id %q", r.GetConfig().GetMetadata(), res.GetPodSandboxId()) } }() res, err = in.c.RunPodSandbox(ctrdutil.WithNamespace(ctx), r) @@ -68,12 +67,12 @@ func (in *instrumentedService) ListPodSandbox(ctx context.Context, r *runtime.Li if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ListPodSandbox with filter %+v", r.GetFilter()) + log.G(ctx).Tracef("ListPodSandbox with filter %+v", r.GetFilter()) defer func() { if err != nil { - logrus.WithError(err).Error("ListPodSandbox failed") + log.G(ctx).WithError(err).Error("ListPodSandbox failed") } else { - log.Tracef("ListPodSandbox returns pod sandboxes %+v", res.GetItems()) + log.G(ctx).Tracef("ListPodSandbox returns pod sandboxes %+v", res.GetItems()) } }() res, err = in.c.ListPodSandbox(ctrdutil.WithNamespace(ctx), r) @@ -84,12 +83,12 @@ func (in *instrumentedService) PodSandboxStatus(ctx context.Context, r *runtime. if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("PodSandboxStatus for %q", r.GetPodSandboxId()) + log.G(ctx).Tracef("PodSandboxStatus for %q", r.GetPodSandboxId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("PodSandboxStatus for %q failed", r.GetPodSandboxId()) + log.G(ctx).WithError(err).Errorf("PodSandboxStatus for %q failed", r.GetPodSandboxId()) } else { - log.Tracef("PodSandboxStatus for %q returns status %+v", r.GetPodSandboxId(), res.GetStatus()) + log.G(ctx).Tracef("PodSandboxStatus for %q returns status %+v", r.GetPodSandboxId(), res.GetStatus()) } }() res, err = in.c.PodSandboxStatus(ctrdutil.WithNamespace(ctx), r) @@ -100,12 +99,12 @@ func (in *instrumentedService) StopPodSandbox(ctx context.Context, r *runtime.St if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("StopPodSandbox for %q", r.GetPodSandboxId()) + log.G(ctx).Infof("StopPodSandbox for %q", r.GetPodSandboxId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("StopPodSandbox for %q failed", r.GetPodSandboxId()) + log.G(ctx).WithError(err).Errorf("StopPodSandbox for %q failed", r.GetPodSandboxId()) } else { - logrus.Infof("StopPodSandbox for %q returns successfully", r.GetPodSandboxId()) + log.G(ctx).Infof("StopPodSandbox for %q returns successfully", r.GetPodSandboxId()) } }() res, err := in.c.StopPodSandbox(ctrdutil.WithNamespace(ctx), r) @@ -116,12 +115,12 @@ func (in *instrumentedService) RemovePodSandbox(ctx context.Context, r *runtime. if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("RemovePodSandbox for %q", r.GetPodSandboxId()) + log.G(ctx).Infof("RemovePodSandbox for %q", r.GetPodSandboxId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("RemovePodSandbox for %q failed", r.GetPodSandboxId()) + log.G(ctx).WithError(err).Errorf("RemovePodSandbox for %q failed", r.GetPodSandboxId()) } else { - logrus.Infof("RemovePodSandbox %q returns successfully", r.GetPodSandboxId()) + log.G(ctx).Infof("RemovePodSandbox %q returns successfully", r.GetPodSandboxId()) } }() res, err := in.c.RemovePodSandbox(ctrdutil.WithNamespace(ctx), r) @@ -132,12 +131,12 @@ func (in *instrumentedService) PortForward(ctx context.Context, r *runtime.PortF if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("Portforward for %q port %v", r.GetPodSandboxId(), r.GetPort()) + log.G(ctx).Infof("Portforward for %q port %v", r.GetPodSandboxId(), r.GetPort()) defer func() { if err != nil { - logrus.WithError(err).Errorf("Portforward for %q failed", r.GetPodSandboxId()) + log.G(ctx).WithError(err).Errorf("Portforward for %q failed", r.GetPodSandboxId()) } else { - logrus.Infof("Portforward for %q returns URL %q", r.GetPodSandboxId(), res.GetUrl()) + log.G(ctx).Infof("Portforward for %q returns URL %q", r.GetPodSandboxId(), res.GetUrl()) } }() res, err = in.c.PortForward(ctrdutil.WithNamespace(ctx), r) @@ -148,14 +147,14 @@ func (in *instrumentedService) CreateContainer(ctx context.Context, r *runtime.C if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("CreateContainer within sandbox %q for container %+v", + log.G(ctx).Infof("CreateContainer within sandbox %q for container %+v", r.GetPodSandboxId(), r.GetConfig().GetMetadata()) defer func() { if err != nil { - logrus.WithError(err).Errorf("CreateContainer within sandbox %q for %+v failed", + log.G(ctx).WithError(err).Errorf("CreateContainer within sandbox %q for %+v failed", r.GetPodSandboxId(), r.GetConfig().GetMetadata()) } else { - logrus.Infof("CreateContainer within sandbox %q for %+v returns container id %q", + log.G(ctx).Infof("CreateContainer within sandbox %q for %+v returns container id %q", r.GetPodSandboxId(), r.GetConfig().GetMetadata(), res.GetContainerId()) } }() @@ -167,12 +166,12 @@ func (in *instrumentedService) StartContainer(ctx context.Context, r *runtime.St if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("StartContainer for %q", r.GetContainerId()) + log.G(ctx).Infof("StartContainer for %q", r.GetContainerId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("StartContainer for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("StartContainer for %q failed", r.GetContainerId()) } else { - logrus.Infof("StartContainer for %q returns successfully", r.GetContainerId()) + log.G(ctx).Infof("StartContainer for %q returns successfully", r.GetContainerId()) } }() res, err := in.c.StartContainer(ctrdutil.WithNamespace(ctx), r) @@ -183,12 +182,12 @@ func (in *instrumentedService) ListContainers(ctx context.Context, r *runtime.Li if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ListContainers with filter %+v", r.GetFilter()) + log.G(ctx).Tracef("ListContainers with filter %+v", r.GetFilter()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ListContainers with filter %+v failed", r.GetFilter()) + log.G(ctx).WithError(err).Errorf("ListContainers with filter %+v failed", r.GetFilter()) } else { - log.Tracef("ListContainers with filter %+v returns containers %+v", + log.G(ctx).Tracef("ListContainers with filter %+v returns containers %+v", r.GetFilter(), res.GetContainers()) } }() @@ -200,12 +199,12 @@ func (in *instrumentedService) ContainerStatus(ctx context.Context, r *runtime.C if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ContainerStatus for %q", r.GetContainerId()) + log.G(ctx).Tracef("ContainerStatus for %q", r.GetContainerId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ContainerStatus for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("ContainerStatus for %q failed", r.GetContainerId()) } else { - log.Tracef("ContainerStatus for %q returns status %+v", r.GetContainerId(), res.GetStatus()) + log.G(ctx).Tracef("ContainerStatus for %q returns status %+v", r.GetContainerId(), res.GetStatus()) } }() res, err = in.c.ContainerStatus(ctrdutil.WithNamespace(ctx), r) @@ -216,12 +215,12 @@ func (in *instrumentedService) StopContainer(ctx context.Context, r *runtime.Sto if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("StopContainer for %q with timeout %d (s)", r.GetContainerId(), r.GetTimeout()) + log.G(ctx).Infof("StopContainer for %q with timeout %d (s)", r.GetContainerId(), r.GetTimeout()) defer func() { if err != nil { - logrus.WithError(err).Errorf("StopContainer for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("StopContainer for %q failed", r.GetContainerId()) } else { - logrus.Infof("StopContainer for %q returns successfully", r.GetContainerId()) + log.G(ctx).Infof("StopContainer for %q returns successfully", r.GetContainerId()) } }() res, err = in.c.StopContainer(ctrdutil.WithNamespace(ctx), r) @@ -232,12 +231,12 @@ func (in *instrumentedService) RemoveContainer(ctx context.Context, r *runtime.R if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("RemoveContainer for %q", r.GetContainerId()) + log.G(ctx).Infof("RemoveContainer for %q", r.GetContainerId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("RemoveContainer for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("RemoveContainer for %q failed", r.GetContainerId()) } else { - logrus.Infof("RemoveContainer for %q returns successfully", r.GetContainerId()) + log.G(ctx).Infof("RemoveContainer for %q returns successfully", r.GetContainerId()) } }() res, err = in.c.RemoveContainer(ctrdutil.WithNamespace(ctx), r) @@ -248,13 +247,13 @@ func (in *instrumentedService) ExecSync(ctx context.Context, r *runtime.ExecSync if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("ExecSync for %q with command %+v and timeout %d (s)", r.GetContainerId(), r.GetCmd(), r.GetTimeout()) + log.G(ctx).Infof("ExecSync for %q with command %+v and timeout %d (s)", r.GetContainerId(), r.GetCmd(), r.GetTimeout()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ExecSync for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("ExecSync for %q failed", r.GetContainerId()) } else { - logrus.Infof("ExecSync for %q returns with exit code %d", r.GetContainerId(), res.GetExitCode()) - logrus.Debugf("ExecSync for %q outputs - stdout: %q, stderr: %q", r.GetContainerId(), + log.G(ctx).Infof("ExecSync for %q returns with exit code %d", r.GetContainerId(), res.GetExitCode()) + log.G(ctx).Debugf("ExecSync for %q outputs - stdout: %q, stderr: %q", r.GetContainerId(), res.GetStdout(), res.GetStderr()) } }() @@ -266,13 +265,13 @@ func (in *instrumentedService) Exec(ctx context.Context, r *runtime.ExecRequest) if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("Exec for %q with command %+v, tty %v and stdin %v", + log.G(ctx).Infof("Exec for %q with command %+v, tty %v and stdin %v", r.GetContainerId(), r.GetCmd(), r.GetTty(), r.GetStdin()) defer func() { if err != nil { - logrus.WithError(err).Errorf("Exec for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("Exec for %q failed", r.GetContainerId()) } else { - logrus.Infof("Exec for %q returns URL %q", r.GetContainerId(), res.GetUrl()) + log.G(ctx).Infof("Exec for %q returns URL %q", r.GetContainerId(), res.GetUrl()) } }() res, err = in.c.Exec(ctrdutil.WithNamespace(ctx), r) @@ -283,12 +282,12 @@ func (in *instrumentedService) Attach(ctx context.Context, r *runtime.AttachRequ if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("Attach for %q with tty %v and stdin %v", r.GetContainerId(), r.GetTty(), r.GetStdin()) + log.G(ctx).Infof("Attach for %q with tty %v and stdin %v", r.GetContainerId(), r.GetTty(), r.GetStdin()) defer func() { if err != nil { - logrus.WithError(err).Errorf("Attach for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("Attach for %q failed", r.GetContainerId()) } else { - logrus.Infof("Attach for %q returns URL %q", r.GetContainerId(), res.Url) + log.G(ctx).Infof("Attach for %q returns URL %q", r.GetContainerId(), res.Url) } }() res, err = in.c.Attach(ctrdutil.WithNamespace(ctx), r) @@ -299,12 +298,12 @@ func (in *instrumentedService) UpdateContainerResources(ctx context.Context, r * if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("UpdateContainerResources for %q with %+v", r.GetContainerId(), r.GetLinux()) + log.G(ctx).Infof("UpdateContainerResources for %q with %+v", r.GetContainerId(), r.GetLinux()) defer func() { if err != nil { - logrus.WithError(err).Errorf("UpdateContainerResources for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("UpdateContainerResources for %q failed", r.GetContainerId()) } else { - logrus.Infof("UpdateContainerResources for %q returns successfully", r.GetContainerId()) + log.G(ctx).Infof("UpdateContainerResources for %q returns successfully", r.GetContainerId()) } }() res, err = in.c.UpdateContainerResources(ctrdutil.WithNamespace(ctx), r) @@ -315,12 +314,12 @@ func (in *instrumentedService) PullImage(ctx context.Context, r *runtime.PullIma if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("PullImage %q", r.GetImage().GetImage()) + log.G(ctx).Infof("PullImage %q", r.GetImage().GetImage()) defer func() { if err != nil { - logrus.WithError(err).Errorf("PullImage %q failed", r.GetImage().GetImage()) + log.G(ctx).WithError(err).Errorf("PullImage %q failed", r.GetImage().GetImage()) } else { - logrus.Infof("PullImage %q returns image reference %q", + log.G(ctx).Infof("PullImage %q returns image reference %q", r.GetImage().GetImage(), res.GetImageRef()) } }() @@ -332,12 +331,12 @@ func (in *instrumentedService) ListImages(ctx context.Context, r *runtime.ListIm if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ListImages with filter %+v", r.GetFilter()) + log.G(ctx).Tracef("ListImages with filter %+v", r.GetFilter()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ListImages with filter %+v failed", r.GetFilter()) + log.G(ctx).WithError(err).Errorf("ListImages with filter %+v failed", r.GetFilter()) } else { - log.Tracef("ListImages with filter %+v returns image list %+v", + log.G(ctx).Tracef("ListImages with filter %+v returns image list %+v", r.GetFilter(), res.GetImages()) } }() @@ -349,12 +348,12 @@ func (in *instrumentedService) ImageStatus(ctx context.Context, r *runtime.Image if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ImageStatus for %q", r.GetImage().GetImage()) + log.G(ctx).Tracef("ImageStatus for %q", r.GetImage().GetImage()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ImageStatus for %q failed", r.GetImage().GetImage()) + log.G(ctx).WithError(err).Errorf("ImageStatus for %q failed", r.GetImage().GetImage()) } else { - log.Tracef("ImageStatus for %q returns image status %+v", + log.G(ctx).Tracef("ImageStatus for %q returns image status %+v", r.GetImage().GetImage(), res.GetImage()) } }() @@ -366,12 +365,12 @@ func (in *instrumentedService) RemoveImage(ctx context.Context, r *runtime.Remov if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Infof("RemoveImage %q", r.GetImage().GetImage()) + log.G(ctx).Infof("RemoveImage %q", r.GetImage().GetImage()) defer func() { if err != nil { - logrus.WithError(err).Errorf("RemoveImage %q failed", r.GetImage().GetImage()) + log.G(ctx).WithError(err).Errorf("RemoveImage %q failed", r.GetImage().GetImage()) } else { - logrus.Infof("RemoveImage %q returns successfully", r.GetImage().GetImage()) + log.G(ctx).Infof("RemoveImage %q returns successfully", r.GetImage().GetImage()) } }() res, err := in.c.RemoveImage(ctrdutil.WithNamespace(ctx), r) @@ -382,12 +381,12 @@ func (in *instrumentedService) ImageFsInfo(ctx context.Context, r *runtime.Image if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Debugf("ImageFsInfo") + log.G(ctx).Debugf("ImageFsInfo") defer func() { if err != nil { - logrus.WithError(err).Error("ImageFsInfo failed") + log.G(ctx).WithError(err).Error("ImageFsInfo failed") } else { - logrus.Debugf("ImageFsInfo returns filesystem info %+v", res.ImageFilesystems) + log.G(ctx).Debugf("ImageFsInfo returns filesystem info %+v", res.ImageFilesystems) } }() res, err = in.c.ImageFsInfo(ctrdutil.WithNamespace(ctx), r) @@ -398,12 +397,12 @@ func (in *instrumentedService) ContainerStats(ctx context.Context, r *runtime.Co if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Debugf("ContainerStats for %q", r.GetContainerId()) + log.G(ctx).Debugf("ContainerStats for %q", r.GetContainerId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ContainerStats for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("ContainerStats for %q failed", r.GetContainerId()) } else { - logrus.Debugf("ContainerStats for %q returns stats %+v", r.GetContainerId(), res.GetStats()) + log.G(ctx).Debugf("ContainerStats for %q returns stats %+v", r.GetContainerId(), res.GetStats()) } }() res, err = in.c.ContainerStats(ctrdutil.WithNamespace(ctx), r) @@ -414,12 +413,12 @@ func (in *instrumentedService) ListContainerStats(ctx context.Context, r *runtim if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("ListContainerStats with filter %+v", r.GetFilter()) + log.G(ctx).Tracef("ListContainerStats with filter %+v", r.GetFilter()) defer func() { if err != nil { - logrus.WithError(err).Error("ListContainerStats failed") + log.G(ctx).WithError(err).Error("ListContainerStats failed") } else { - log.Tracef("ListContainerStats returns stats %+v", res.GetStats()) + log.G(ctx).Tracef("ListContainerStats returns stats %+v", res.GetStats()) } }() res, err = in.c.ListContainerStats(ctrdutil.WithNamespace(ctx), r) @@ -430,12 +429,12 @@ func (in *instrumentedService) Status(ctx context.Context, r *runtime.StatusRequ if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("Status") + log.G(ctx).Tracef("Status") defer func() { if err != nil { - logrus.WithError(err).Error("Status failed") + log.G(ctx).WithError(err).Error("Status failed") } else { - log.Tracef("Status returns status %+v", res.GetStatus()) + log.G(ctx).Tracef("Status returns status %+v", res.GetStatus()) } }() res, err = in.c.Status(ctrdutil.WithNamespace(ctx), r) @@ -446,12 +445,12 @@ func (in *instrumentedService) Version(ctx context.Context, r *runtime.VersionRe if err := in.checkInitialized(); err != nil { return nil, err } - log.Tracef("Version with client side version %q", r.GetVersion()) + log.G(ctx).Tracef("Version with client side version %q", r.GetVersion()) defer func() { if err != nil { - logrus.WithError(err).Error("Version failed") + log.G(ctx).WithError(err).Error("Version failed") } else { - log.Tracef("Version returns %+v", res) + log.G(ctx).Tracef("Version returns %+v", res) } }() res, err = in.c.Version(ctrdutil.WithNamespace(ctx), r) @@ -462,12 +461,12 @@ func (in *instrumentedService) UpdateRuntimeConfig(ctx context.Context, r *runti if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Debugf("UpdateRuntimeConfig with config %+v", r.GetRuntimeConfig()) + log.G(ctx).Debugf("UpdateRuntimeConfig with config %+v", r.GetRuntimeConfig()) defer func() { if err != nil { - logrus.WithError(err).Error("UpdateRuntimeConfig failed") + log.G(ctx).WithError(err).Error("UpdateRuntimeConfig failed") } else { - logrus.Debug("UpdateRuntimeConfig returns returns successfully") + log.G(ctx).Debug("UpdateRuntimeConfig returns returns successfully") } }() res, err = in.c.UpdateRuntimeConfig(ctrdutil.WithNamespace(ctx), r) @@ -478,12 +477,12 @@ func (in *instrumentedService) ReopenContainerLog(ctx context.Context, r *runtim if err := in.checkInitialized(); err != nil { return nil, err } - logrus.Debugf("ReopenContainerLog for %q", r.GetContainerId()) + log.G(ctx).Debugf("ReopenContainerLog for %q", r.GetContainerId()) defer func() { if err != nil { - logrus.WithError(err).Errorf("ReopenContainerLog for %q failed", r.GetContainerId()) + log.G(ctx).WithError(err).Errorf("ReopenContainerLog for %q failed", r.GetContainerId()) } else { - logrus.Debugf("ReopenContainerLog for %q returns successfully", r.GetContainerId()) + log.G(ctx).Debugf("ReopenContainerLog for %q returns successfully", r.GetContainerId()) } }() res, err = in.c.ReopenContainerLog(ctrdutil.WithNamespace(ctx), r) diff --git a/vendor/github.com/containerd/cri/pkg/server/restart.go b/vendor/github.com/containerd/cri/pkg/server/restart.go index e694896ce..30b1fa625 100644 --- a/vendor/github.com/containerd/cri/pkg/server/restart.go +++ b/vendor/github.com/containerd/cri/pkg/server/restart.go @@ -26,11 +26,11 @@ import ( containerdio "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" containerdimages "github.com/containerd/containerd/images" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/platforms" "github.com/containerd/typeurl" "github.com/docker/docker/pkg/system" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -60,10 +60,10 @@ func (c *criService) recover(ctx context.Context) error { for _, sandbox := range sandboxes { sb, err := c.loadSandbox(ctx, sandbox) if err != nil { - logrus.WithError(err).Errorf("Failed to load sandbox %q", sandbox.ID()) + log.G(ctx).WithError(err).Errorf("Failed to load sandbox %q", sandbox.ID()) continue } - logrus.Debugf("Loaded sandbox %+v", sb) + log.G(ctx).Debugf("Loaded sandbox %+v", sb) if err := c.sandboxStore.Add(sb); err != nil { return errors.Wrapf(err, "failed to add sandbox %q to store", sandbox.ID()) } @@ -80,10 +80,10 @@ func (c *criService) recover(ctx context.Context) error { for _, container := range containers { cntr, err := c.loadContainer(ctx, container) if err != nil { - logrus.WithError(err).Errorf("Failed to load container %q", container.ID()) + log.G(ctx).WithError(err).Errorf("Failed to load container %q", container.ID()) continue } - logrus.Debugf("Loaded container %+v", cntr) + log.G(ctx).Debugf("Loaded container %+v", cntr) if err := c.containerStore.Add(cntr); err != nil { return errors.Wrapf(err, "failed to add container %q to store", container.ID()) } @@ -130,7 +130,7 @@ func (c *criService) recover(ctx context.Context) error { errMsg: "failed to cleanup orphaned volatile container directories", }, } { - if err := cleanupOrphanedIDDirs(cleanup.cntrs, cleanup.base); err != nil { + if err := cleanupOrphanedIDDirs(ctx, cleanup.cntrs, cleanup.base); err != nil { return errors.Wrap(err, cleanup.errMsg) } } @@ -176,7 +176,7 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe // Load status from checkpoint. status, err := containerstore.LoadStatus(containerDir, id) if err != nil { - logrus.WithError(err).Warnf("Failed to load container status for %q", id) + log.G(ctx).WithError(err).Warnf("Failed to load container status for %q", id) status = unknownContainerStatus() } @@ -306,7 +306,7 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe return nil }() if err != nil { - logrus.WithError(err).Errorf("Failed to load container status for %q", id) + log.G(ctx).WithError(err).Errorf("Failed to load container status for %q", id) status = unknownContainerStatus() } opts := []containerstore.Opts{ @@ -400,7 +400,7 @@ func (c *criService) loadSandbox(ctx context.Context, cntr containerd.Container) return status, nil }() if err != nil { - logrus.WithError(err).Errorf("Failed to load sandbox status for %q", cntr.ID()) + log.G(ctx).WithError(err).Errorf("Failed to load sandbox status for %q", cntr.ID()) } sandbox = sandboxstore.NewSandbox(*meta, s) @@ -425,32 +425,32 @@ func (c *criService) loadImages(ctx context.Context, cImages []containerd.Image) for _, i := range cImages { ok, _, _, _, err := containerdimages.Check(ctx, i.ContentStore(), i.Target(), platforms.Default()) if err != nil { - logrus.WithError(err).Errorf("Failed to check image content readiness for %q", i.Name()) + log.G(ctx).WithError(err).Errorf("Failed to check image content readiness for %q", i.Name()) continue } if !ok { - logrus.Warnf("The image content readiness for %q is not ok", i.Name()) + log.G(ctx).Warnf("The image content readiness for %q is not ok", i.Name()) continue } // Checking existence of top-level snapshot for each image being recovered. unpacked, err := i.IsUnpacked(ctx, snapshotter) if err != nil { - logrus.WithError(err).Warnf("Failed to check whether image is unpacked for image %s", i.Name()) + log.G(ctx).WithError(err).Warnf("Failed to check whether image is unpacked for image %s", i.Name()) continue } if !unpacked { - logrus.Warnf("The image %s is not unpacked.", i.Name()) + log.G(ctx).Warnf("The image %s is not unpacked.", i.Name()) // TODO(random-liu): Consider whether we should try unpack here. } if err := c.updateImage(ctx, i.Name()); err != nil { - logrus.WithError(err).Warnf("Failed to update reference for image %q", i.Name()) + log.G(ctx).WithError(err).Warnf("Failed to update reference for image %q", i.Name()) continue } - logrus.Debugf("Loaded image %q", i.Name()) + log.G(ctx).Debugf("Loaded image %q", i.Name()) } } -func cleanupOrphanedIDDirs(cntrs []containerd.Container, base string) error { +func cleanupOrphanedIDDirs(ctx context.Context, cntrs []containerd.Container, base string) error { // Cleanup orphaned id directories. dirs, err := ioutil.ReadDir(base) if err != nil && !os.IsNotExist(err) { @@ -462,7 +462,7 @@ func cleanupOrphanedIDDirs(cntrs []containerd.Container, base string) error { } for _, d := range dirs { if !d.IsDir() { - logrus.Warnf("Invalid file %q found in base directory %q", d.Name(), base) + log.G(ctx).Warnf("Invalid file %q found in base directory %q", d.Name(), base) continue } if _, ok := idsMap[d.Name()]; ok { @@ -471,9 +471,9 @@ func cleanupOrphanedIDDirs(cntrs []containerd.Container, base string) error { } dir := filepath.Join(base, d.Name()) if err := system.EnsureRemoveAll(dir); err != nil { - logrus.WithError(err).Warnf("Failed to remove id directory %q", dir) + log.G(ctx).WithError(err).Warnf("Failed to remove id directory %q", dir) } else { - logrus.Debugf("Cleanup orphaned id directory %q", dir) + log.G(ctx).Debugf("Cleanup orphaned id directory %q", dir) } } return nil diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go index cd8409d02..f972ce207 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_portforward.go @@ -23,6 +23,7 @@ import ( "os/exec" "strings" + "github.com/containerd/containerd/log" "github.com/containernetworking/plugins/pkg/ns" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -48,7 +49,7 @@ func (c *criService) PortForward(ctx context.Context, r *runtime.PortForwardRequ // portForward requires `socat` on the node. It uses netns to enter the sandbox namespace, // and run `socat` insidethe namespace to forward stream for a specific port. The `socat` // command keeps running until it exits or client disconnect. -func (c *criService) portForward(id string, port int32, stream io.ReadWriteCloser) error { +func (c *criService) portForward(ctx context.Context, id string, port int32, stream io.ReadWriter) error { s, err := c.sandboxStore.Get(id) if err != nil { return errors.Wrapf(err, "failed to find sandbox %q in store", id) @@ -82,7 +83,7 @@ func (c *criService) portForward(id string, port int32, stream io.ReadWriteClose // Check https://linux.die.net/man/1/socat for meaning of the options. args := []string{socat, "-", fmt.Sprintf("TCP4:localhost:%d", port)} - logrus.Infof("Executing port forwarding command %q in network namespace %q", strings.Join(args, " "), netNSPath) + log.G(ctx).Infof("Executing port forwarding command %q in network namespace %q", strings.Join(args, " "), netNSPath) err = netNSDo(func(_ ns.NetNS) error { cmd := exec.Command(args[0], args[1:]...) cmd.Stdout = stream @@ -119,7 +120,7 @@ func (c *criService) portForward(id string, port int32, stream io.ReadWriteClose if err != nil { return errors.Wrapf(err, "failed to execute portforward in network namespace %q", netNSPath) } - logrus.Infof("Finish port forwarding for %q port %d", id, port) + log.G(ctx).Infof("Finish port forwarding for %q port %d", id, port) return nil } diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go index 8eb6e46f6..017c56cef 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_remove.go @@ -19,12 +19,12 @@ package server import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/docker/docker/pkg/system" "github.com/pkg/errors" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "github.com/containerd/cri/pkg/log" "github.com/containerd/cri/pkg/store" sandboxstore "github.com/containerd/cri/pkg/store/sandbox" ) @@ -39,7 +39,7 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS r.GetPodSandboxId()) } // Do not return error if the id doesn't exist. - log.Tracef("RemovePodSandbox called for sandbox %q that does not exist", + log.G(ctx).Tracef("RemovePodSandbox called for sandbox %q that does not exist", r.GetPodSandboxId()) return &runtime.RemovePodSandboxResponse{}, nil } @@ -95,7 +95,7 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS if !errdefs.IsNotFound(err) { return nil, errors.Wrapf(err, "failed to delete sandbox container %q", id) } - log.Tracef("Remove called for sandbox container %q that does not exist", id) + log.G(ctx).Tracef("Remove called for sandbox container %q that does not exist", id) } // Remove sandbox from sandbox store. Note that once the sandbox is successfully diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go index 0718dbc6f..39e03a116 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd" containerdio "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/plugin" cni "github.com/containerd/go-cni" @@ -44,7 +45,6 @@ import ( criconfig "github.com/containerd/cri/pkg/config" customopts "github.com/containerd/cri/pkg/containerd/opts" ctrdutil "github.com/containerd/cri/pkg/containerd/util" - "github.com/containerd/cri/pkg/log" "github.com/containerd/cri/pkg/netns" sandboxstore "github.com/containerd/cri/pkg/store/sandbox" "github.com/containerd/cri/pkg/util" @@ -59,7 +59,7 @@ func init() { // the sandbox is in ready state. func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandboxRequest) (_ *runtime.RunPodSandboxResponse, retErr error) { config := r.GetConfig() - logrus.Debugf("Sandbox config %+v", config) + log.G(ctx).Debugf("Sandbox config %+v", config) // Generate unique id and name for the sandbox and reserve the name. id := util.GenerateID() @@ -68,7 +68,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox return nil, errors.New("sandbox config must include metadata") } name := makeSandboxName(metadata) - logrus.Debugf("Generated id %q for sandbox %q", id, name) + log.G(ctx).Debugf("Generated id %q for sandbox %q", id, name) // Reserve the sandbox name to avoid concurrent `RunPodSandbox` request starting the // same sandbox. if err := c.sandboxNameIndex.Reserve(name, id); err != nil { @@ -108,7 +108,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox if err != nil { return nil, errors.Wrap(err, "failed to get sandbox runtime") } - logrus.Debugf("Use OCI %+v for sandbox %q", ociRuntime, id) + log.G(ctx).Debugf("Use OCI %+v for sandbox %q", ociRuntime, id) securityContext := config.GetLinux().GetSecurityContext() //Create Network Namespace if it is not in host network @@ -126,7 +126,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox defer func() { if retErr != nil { if err := sandbox.NetNS.Remove(); err != nil { - logrus.WithError(err).Errorf("Failed to remove network namespace %s for sandbox %q", sandbox.NetNSPath, id) + log.G(ctx).WithError(err).Errorf("Failed to remove network namespace %s for sandbox %q", sandbox.NetNSPath, id) } sandbox.NetNSPath = "" } @@ -139,15 +139,15 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // In this case however caching the IP will add a subtle performance enhancement by avoiding // calls to network namespace of the pod to query the IP of the veth interface on every // SandboxStatus request. - sandbox.IP, sandbox.CNIResult, err = c.setupPod(id, sandbox.NetNSPath, config) + sandbox.IP, sandbox.CNIResult, err = c.setupPod(ctx, id, sandbox.NetNSPath, config) if err != nil { return nil, errors.Wrapf(err, "failed to setup network for sandbox %q", id) } defer func() { if retErr != nil { // Teardown network if an error is returned. - if err := c.teardownPod(id, sandbox.NetNSPath, config); err != nil { - logrus.WithError(err).Errorf("Failed to destroy network for sandbox %q", id) + if err := c.teardownPod(ctx, id, sandbox.NetNSPath, config); err != nil { + log.G(ctx).WithError(err).Errorf("Failed to destroy network for sandbox %q", id) } } }() @@ -158,7 +158,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox if err != nil { return nil, errors.Wrap(err, "failed to generate sandbox container spec") } - logrus.Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec)) + log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec)) var specOpts []oci.SpecOpts userstr, err := generateUserString( @@ -169,6 +169,11 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox if err != nil { return nil, errors.Wrap(err, "failed to generate user string") } + if userstr == "" { + // Lastly, since no user override was passed via CRI try to set via OCI + // Image + userstr = image.ImageSpec.Config.User + } if userstr != "" { specOpts = append(specOpts, oci.WithUser(userstr)) } @@ -207,7 +212,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox deferCtx, deferCancel := ctrdutil.DeferContext() defer deferCancel() if err := container.Delete(deferCtx, containerd.WithSnapshotCleanup); err != nil { - logrus.WithError(err).Errorf("Failed to delete containerd container %q", id) + log.G(ctx).WithError(err).Errorf("Failed to delete containerd container %q", id) } } }() @@ -222,7 +227,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox if retErr != nil { // Cleanup the sandbox root directory. if err := c.os.RemoveAll(sandboxRootDir); err != nil { - logrus.WithError(err).Errorf("Failed to remove sandbox root directory %q", + log.G(ctx).WithError(err).Errorf("Failed to remove sandbox root directory %q", sandboxRootDir) } } @@ -236,7 +241,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox if retErr != nil { // Cleanup the volatile sandbox root directory. if err := c.os.RemoveAll(volatileSandboxRootDir); err != nil { - logrus.WithError(err).Errorf("Failed to remove volatile sandbox root directory %q", + log.G(ctx).WithError(err).Errorf("Failed to remove volatile sandbox root directory %q", volatileSandboxRootDir) } } @@ -249,7 +254,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox defer func() { if retErr != nil { if err = c.unmountSandboxFiles(id, config); err != nil { - logrus.WithError(err).Errorf("Failed to unmount sandbox files in %q", + log.G(ctx).WithError(err).Errorf("Failed to unmount sandbox files in %q", sandboxRootDir) } } @@ -262,7 +267,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox } // Create sandbox task in containerd. - log.Tracef("Create sandbox container (id=%q, name=%q).", + log.G(ctx).Tracef("Create sandbox container (id=%q, name=%q).", id, name) var taskOpts []containerd.NewTaskOpts @@ -281,7 +286,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox defer deferCancel() // Cleanup the sandbox container if an error is returned. if _, err := task.Delete(deferCtx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Errorf("Failed to delete sandbox container %q", id) + log.G(ctx).WithError(err).Errorf("Failed to delete sandbox container %q", id) } } }() @@ -352,8 +357,7 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod specOpts = append(specOpts, customopts.WithDisabledCgroups) } else { if config.GetLinux().GetCgroupParent() != "" { - cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id, - c.config.SystemdCgroup) + cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id) specOpts = append(specOpts, oci.WithCgroup(cgroupsPath)) } } @@ -541,7 +545,7 @@ func (c *criService) unmountSandboxFiles(id string, config *runtime.PodSandboxCo } // setupPod setups up the network for a pod -func (c *criService) setupPod(id string, path string, config *runtime.PodSandboxConfig) (string, *cni.CNIResult, error) { +func (c *criService) setupPod(ctx context.Context, id string, path string, config *runtime.PodSandboxConfig) (string, *cni.CNIResult, error) { if c.netPlugin == nil { return "", nil, errors.New("cni config not initialized") } @@ -555,7 +559,7 @@ func (c *criService) setupPod(id string, path string, config *runtime.PodSandbox return "", nil, errors.Wrap(err, "failed to get bandwidth info from annotations") } - result, err := c.netPlugin.Setup(id, + result, err := c.netPlugin.Setup(ctx, id, path, cni.WithLabels(labels), cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings())), @@ -565,14 +569,14 @@ func (c *criService) setupPod(id string, path string, config *runtime.PodSandbox if err != nil { return "", nil, err } - logDebugCNIResult(id, result) + logDebugCNIResult(ctx, id, result) // Check if the default interface has IP config if configs, ok := result.Interfaces[defaultIfName]; ok && len(configs.IPConfigs) > 0 { return selectPodIP(configs.IPConfigs), result, nil } // If it comes here then the result was invalid so destroy the pod network and return error - if err := c.teardownPod(id, path, config); err != nil { - logrus.WithError(err).Errorf("Failed to destroy network for sandbox %q", id) + if err := c.teardownPod(ctx, id, path, config); err != nil { + log.G(ctx).WithError(err).Errorf("Failed to destroy network for sandbox %q", id) } return "", result, errors.Errorf("failed to find network info for sandbox %q", id) } @@ -682,14 +686,14 @@ func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig, runtime return handler, nil } -func logDebugCNIResult(sandboxID string, result *cni.CNIResult) { +func logDebugCNIResult(ctx context.Context, sandboxID string, result *cni.CNIResult) { if logrus.GetLevel() < logrus.DebugLevel { return } cniResult, err := json.Marshal(result) if err != nil { - logrus.WithError(err).Errorf("Failed to marshal CNI result for sandbox %q: %v", sandboxID, err) + log.G(ctx).WithError(err).Errorf("Failed to marshal CNI result for sandbox %q: %v", sandboxID, err) return } - logrus.Debugf("cni result for sandbox %q: %s", sandboxID, string(cniResult)) + log.G(ctx).Debugf("cni result for sandbox %q: %s", sandboxID, string(cniResult)) } diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go index 852769f1a..0796f5cfd 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_stop.go @@ -22,9 +22,9 @@ import ( eventtypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" cni "github.com/containerd/go-cni" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -80,7 +80,7 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb } else if closed { netNSPath = "" } - if err := c.teardownPod(id, netNSPath, sandbox.Config); err != nil { + if err := c.teardownPod(ctx, id, netNSPath, sandbox.Config); err != nil { return nil, errors.Wrapf(err, "failed to destroy network for sandbox %q", id) } if err = sandbox.NetNS.Remove(); err != nil { @@ -88,7 +88,7 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb } } - logrus.Infof("TearDown network for sandbox %q successfully", id) + log.G(ctx).Infof("TearDown network for sandbox %q successfully", id) return &runtime.StopPodSandboxResponse{}, nil } @@ -157,13 +157,13 @@ func (c *criService) waitSandboxStop(ctx context.Context, sandbox sandboxstore.S } // teardownPod removes the network from the pod -func (c *criService) teardownPod(id string, path string, config *runtime.PodSandboxConfig) error { +func (c *criService) teardownPod(ctx context.Context, id string, path string, config *runtime.PodSandboxConfig) error { if c.netPlugin == nil { return errors.New("cni config not initialized") } labels := getPodCNILabels(id, config) - return c.netPlugin.Remove(id, + return c.netPlugin.Remove(ctx, id, path, cni.WithLabels(labels), cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings()))) diff --git a/vendor/github.com/containerd/cri/pkg/server/status.go b/vendor/github.com/containerd/cri/pkg/server/status.go index faa8b8e33..a55f3d3a4 100644 --- a/vendor/github.com/containerd/cri/pkg/server/status.go +++ b/vendor/github.com/containerd/cri/pkg/server/status.go @@ -21,8 +21,8 @@ import ( "fmt" goruntime "runtime" + "github.com/containerd/containerd/log" cni "github.com/containerd/go-cni" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" ) @@ -45,7 +45,7 @@ func (c *criService) Status(ctx context.Context, r *runtime.StatusRequest) (*run // Load the latest cni configuration to be in sync with the latest network configuration if err := c.netPlugin.Load(cni.WithLoNetwork, cni.WithDefaultConf); err != nil { - logrus.WithError(err).Errorf("Failed to load cni configuration") + log.G(ctx).WithError(err).Errorf("Failed to load cni configuration") } // Check the status of the cni initialization if err := c.netPlugin.Status(); err != nil { @@ -75,7 +75,7 @@ func (c *criService) Status(ctx context.Context, r *runtime.StatusRequest) (*run cniConfig, err := json.Marshal(c.netPlugin.GetConfig()) if err != nil { - logrus.WithError(err).Errorf("Failed to marshal CNI config %v", err) + log.G(ctx).WithError(err).Errorf("Failed to marshal CNI config %v", err) } resp.Info["cniconfig"] = string(cniConfig) } diff --git a/vendor/github.com/containerd/cri/pkg/server/streaming.go b/vendor/github.com/containerd/cri/pkg/server/streaming.go index 43e1db0a2..e26647470 100644 --- a/vendor/github.com/containerd/cri/pkg/server/streaming.go +++ b/vendor/github.com/containerd/cri/pkg/server/streaming.go @@ -25,6 +25,7 @@ import ( "time" "github.com/pkg/errors" + "golang.org/x/net/context" k8snet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/tools/remotecommand" @@ -155,7 +156,7 @@ func (s *streamRuntime) PortForward(podSandboxID string, port int32, stream io.R if port <= 0 || port > math.MaxUint16 { return errors.Errorf("invalid port %d", port) } - return s.c.portForward(podSandboxID, port, stream) + return s.c.portForward(context.Background(), podSandboxID, port, stream) } // handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each diff --git a/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go b/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go index 5ce5805f5..ca2684f3b 100644 --- a/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go +++ b/vendor/github.com/containerd/cri/pkg/server/update_runtime_config.go @@ -21,9 +21,9 @@ import ( "path/filepath" "text/template" + "github.com/containerd/containerd/log" cni "github.com/containerd/go-cni" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" ) @@ -46,17 +46,17 @@ func (c *criService) UpdateRuntimeConfig(ctx context.Context, r *runtime.UpdateR } confTemplate := c.config.NetworkPluginConfTemplate if confTemplate == "" { - logrus.Info("No cni config template is specified, wait for other system components to drop the config.") + log.G(ctx).Info("No cni config template is specified, wait for other system components to drop the config.") return &runtime.UpdateRuntimeConfigResponse{}, nil } if err := c.netPlugin.Status(); err == nil { - logrus.Infof("Network plugin is ready, skip generating cni config from template %q", confTemplate) + log.G(ctx).Infof("Network plugin is ready, skip generating cni config from template %q", confTemplate) return &runtime.UpdateRuntimeConfigResponse{}, nil } else if err := c.netPlugin.Load(cni.WithLoNetwork, cni.WithDefaultConf); err == nil { - logrus.Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate) + log.G(ctx).Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate) return &runtime.UpdateRuntimeConfigResponse{}, nil } - logrus.Infof("Generating cni config from template %q", confTemplate) + log.G(ctx).Infof("Generating cni config from template %q", confTemplate) // generate cni config file from the template with updated pod cidr. t, err := template.ParseFiles(confTemplate) if err != nil { diff --git a/vendor/github.com/containerd/cri/vendor.conf b/vendor/github.com/containerd/cri/vendor.conf index 38a875a5f..efe3b0910 100644 --- a/vendor/github.com/containerd/cri/vendor.conf +++ b/vendor/github.com/containerd/cri/vendor.conf @@ -1,72 +1,80 @@ -github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 -github.com/BurntSushi/toml v0.3.1 -github.com/containerd/cgroups db272301ab8449d05f062e6db6f13d8a6aaff466 -github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f -github.com/containerd/containerd 31afff294400b5a69bdb3ec387ecdf5bad57a038 -github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 -github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/containerd/go-cni 22460c018b64cf8bf4151b3ff9c4d077e6a88cbf -github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 -github.com/containerd/ttrpc a5bd8ce9e40bc7c065a11c6936f4d032ce6bfa2b -github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 -github.com/containernetworking/cni v0.6.0 -github.com/containernetworking/plugins v0.7.5 -github.com/coreos/go-systemd v14 -github.com/davecgh/go-spew v1.1.0 -github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580 -github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 -github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 -github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 -github.com/docker/go-units v0.4.0 -github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 -github.com/emicklei/go-restful v2.2.1 -github.com/godbus/dbus v3 -github.com/gogo/googleapis v1.2.0 -github.com/gogo/protobuf v1.2.1 -github.com/golang/protobuf v1.2.0 -github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c -github.com/grpc-ecosystem/go-grpc-prometheus v1.1 -github.com/json-iterator/go 1.1.5 -github.com/matttproud/golang_protobuf_extensions v1.0.1 -github.com/Microsoft/go-winio 84b4ab48a50763fe7b3abcef38e5205c12027fac -github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517 -github.com/modern-go/concurrent 1.0.3 -github.com/modern-go/reflect2 1.0.1 -github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 -github.com/opencontainers/image-spec v1.0.1 -github.com/opencontainers/runc v1.0.0-rc8 -github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 -github.com/opencontainers/selinux v1.2.2 -github.com/pkg/errors v0.8.1 -github.com/pmezard/go-difflib v1.0.0 -github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823 -github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c -github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563 -github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd -github.com/seccomp/libseccomp-golang v0.9.1 -github.com/sirupsen/logrus v1.4.1 -github.com/stretchr/testify v1.1.4 -github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 +# cri dependencies github.com/tchap/go-patricia v2.2.6 -github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c +github.com/opencontainers/selinux v1.2.2 +github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 +github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580 + +# containerd dependencies go.etcd.io/bbolt 2eb7227adea1d5cf85f0bc2a82b7059b13c2fa68 -golang.org/x/crypto 88737f569e3a9c7ab309cdc09a07fe7fc87233c3 -golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3 -golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 -golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e -golang.org/x/sys 4c4f7f33c9ed00de01c4c741d2177abfcfe19307 https://github.com/golang/sys -golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 -golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 +google.golang.org/grpc 25c4f928eaa6d96443009bd842389fb4fa48664e # v1.20.1 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 -google.golang.org/grpc 25c4f928eaa6d96443009bd842389fb4fa48664e -gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 -gopkg.in/yaml.v2 v2.2.1 -k8s.io/api kubernetes-1.15.0 -k8s.io/apimachinery kubernetes-1.15.0 -k8s.io/apiserver kubernetes-1.15.0 +golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 +golang.org/x/sys 4c4f7f33c9ed00de01c4c741d2177abfcfe19307 https://github.com/golang/sys +golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e +golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3 +github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c +github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 +github.com/sirupsen/logrus v1.4.1 +github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd +github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563 +github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c +github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823 +github.com/pkg/errors v0.8.1 +github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db +github.com/opencontainers/runc f4982d86f7fde0b6f953cc62ccc4022c519a10a9 # v1.0.0-rc8-32-gf4982d86 +github.com/opencontainers/image-spec v1.0.1 +github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 +github.com/matttproud/golang_protobuf_extensions v1.0.1 +github.com/grpc-ecosystem/go-grpc-prometheus v1.1 +github.com/google/uuid v1.1.1 +github.com/golang/protobuf v1.2.0 +github.com/gogo/protobuf v1.2.1 +github.com/gogo/googleapis v1.2.0 +github.com/godbus/dbus v3 +github.com/docker/go-units v0.4.0 +github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 +github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 +github.com/coreos/go-systemd v14 +github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 +github.com/containerd/ttrpc 1fb3814edf44a76e0ccf503decf726d994919a9a +github.com/containerd/go-runc 9007c2405372fe28918845901a3276c0915689a1 +github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c +github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 +github.com/containerd/containerd a3a30635ef713b544ea7feff0d12a768fd1ed636 +github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f +github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9 +github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 +github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517 +github.com/Microsoft/go-winio v0.4.14 +github.com/BurntSushi/toml v0.3.1 + +# kubernetes dependencies +sigs.k8s.io/yaml v1.1.0 +k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c +k8s.io/kubernetes v1.15.0 +k8s.io/klog v0.3.1 k8s.io/cri-api kubernetes-1.15.0 k8s.io/client-go kubernetes-1.15.0 -k8s.io/klog v0.3.1 -k8s.io/kubernetes v1.15.0 -k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c -sigs.k8s.io/yaml v1.1.0 +k8s.io/api kubernetes-1.15.0 +k8s.io/apiserver kubernetes-1.15.0 +k8s.io/apimachinery kubernetes-1.15.0 +gopkg.in/yaml.v2 v2.2.1 +gopkg.in/inf.v0 v0.9.0 +golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 +golang.org/x/oauth2 9f3314589c9a9136388751d9adae6b0ed400978a +golang.org/x/crypto 88737f569e3a9c7ab309cdc09a07fe7fc87233c3 +github.com/stretchr/testify v1.2.2 +github.com/seccomp/libseccomp-golang v0.9.1 +github.com/pmezard/go-difflib v1.0.0 +github.com/modern-go/reflect2 1.0.1 +github.com/modern-go/concurrent 1.0.3 +github.com/json-iterator/go 1.1.5 +github.com/google/gofuzz 24818f796faf91cd76ec7bddd72458fbced7a6c1 +github.com/emicklei/go-restful v2.2.1 +github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 +github.com/davecgh/go-spew v1.1.1 + +# cni dependencies +github.com/containernetworking/plugins v0.7.6 +github.com/containernetworking/cni v0.7.1 +github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1 diff --git a/vendor/github.com/containerd/go-cni/README.md b/vendor/github.com/containerd/go-cni/README.md index fea3ce29f..1bd2f0013 100644 --- a/vendor/github.com/containerd/go-cni/README.md +++ b/vendor/github.com/containerd/go-cni/README.md @@ -12,7 +12,7 @@ A generic CNI library to provide APIs for CNI plugin interactions. The library p go-cni aims to support plugins that implement [Container Network Interface](https://github.com/containernetworking/cni) ## Usage -``` +```go func main() { id := "123456" netns := "/proc/9999/ns/net" @@ -24,7 +24,7 @@ func main() { gocni.WithDefaultIfName(defaultIfName)) // Load the cni configuration - err:= l.Load(gocni.WithLoNetwork,gocni.WithDefaultConf) + err:= l.Load(gocni.WithLoNetwork, gocni.WithDefaultConf) if err != nil{ log.Errorf("failed to load cni configuration: %v", err) return diff --git a/vendor/github.com/containerd/go-cni/cni.go b/vendor/github.com/containerd/go-cni/cni.go index bdd63b841..8acc83b33 100644 --- a/vendor/github.com/containerd/go-cni/cni.go +++ b/vendor/github.com/containerd/go-cni/cni.go @@ -17,6 +17,7 @@ package cni import ( + "context" "fmt" "strings" "sync" @@ -29,9 +30,9 @@ import ( type CNI interface { // Setup setup the network for the namespace - Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error) + Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*CNIResult, error) // Remove tears down the network of the namespace. - Remove(id string, path string, opts ...NamespaceOpts) error + Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error // Load loads the cni network config Load(opts ...CNIOpt) error // Status checks the status of the cni initialization @@ -139,7 +140,7 @@ func (c *libcni) Networks() []*Network { } // Setup setups the network in the namespace -func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error) { +func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*CNIResult, error) { if err := c.Status(); err != nil { return nil, err } @@ -149,7 +150,7 @@ func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResul } var results []*current.Result for _, network := range c.Networks() { - r, err := network.Attach(ns) + r, err := network.Attach(ctx, ns) if err != nil { return nil, err } @@ -159,7 +160,7 @@ func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResul } // Remove removes the network config from the namespace -func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error { +func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error { if err := c.Status(); err != nil { return err } @@ -168,7 +169,7 @@ func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error { return err } for _, network := range c.Networks() { - if err := network.Remove(ns); err != nil { + if err := network.Remove(ctx, ns); err != nil { // Based on CNI spec v0.7.0, empty network namespace is allowed to // do best effort cleanup. However, it is not handled consistently // right now: diff --git a/vendor/github.com/containerd/go-cni/helper.go b/vendor/github.com/containerd/go-cni/helper.go index 6cde2b332..088cb9bc5 100644 --- a/vendor/github.com/containerd/go-cni/helper.go +++ b/vendor/github.com/containerd/go-cni/helper.go @@ -24,10 +24,10 @@ import ( func validateInterfaceConfig(ipConf *current.IPConfig, ifs int) error { if ipConf == nil { - return fmt.Errorf("invalid IP configuration") + return fmt.Errorf("invalid IP configuration (nil)") } if ipConf.Interface != nil && *ipConf.Interface > ifs { - return fmt.Errorf("invalid IP configuration with invalid interface %d", *ipConf.Interface) + return fmt.Errorf("invalid IP configuration (interface number %d is > number of interfaces %d)", *ipConf.Interface, ifs) } return nil } diff --git a/vendor/github.com/containerd/go-cni/namespace.go b/vendor/github.com/containerd/go-cni/namespace.go index 746c995eb..ff14b01c1 100644 --- a/vendor/github.com/containerd/go-cni/namespace.go +++ b/vendor/github.com/containerd/go-cni/namespace.go @@ -17,6 +17,8 @@ package cni import ( + "context" + cnilibrary "github.com/containernetworking/cni/libcni" "github.com/containernetworking/cni/pkg/types/current" ) @@ -27,16 +29,16 @@ type Network struct { ifName string } -func (n *Network) Attach(ns *Namespace) (*current.Result, error) { - r, err := n.cni.AddNetworkList(n.config, ns.config(n.ifName)) +func (n *Network) Attach(ctx context.Context, ns *Namespace) (*current.Result, error) { + r, err := n.cni.AddNetworkList(ctx, n.config, ns.config(n.ifName)) if err != nil { return nil, err } return current.NewResultFromResult(r) } -func (n *Network) Remove(ns *Namespace) error { - return n.cni.DelNetworkList(n.config, ns.config(n.ifName)) +func (n *Network) Remove(ctx context.Context, ns *Namespace) error { + return n.cni.DelNetworkList(ctx, n.config, ns.config(n.ifName)) } type Namespace struct { diff --git a/vendor/github.com/containerd/go-cni/opts.go b/vendor/github.com/containerd/go-cni/opts.go index 4a6f66d05..5222df1e9 100644 --- a/vendor/github.com/containerd/go-cni/opts.go +++ b/vendor/github.com/containerd/go-cni/opts.go @@ -220,11 +220,11 @@ func loadFromConfDir(c *libcni, max int) error { confList, err = cnilibrary.ConfListFromConf(conf) if err != nil { - return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to list: %v", confFile, err) + return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to CNI config list: %v", confFile, err) } } if len(confList.Plugins) == 0 { - return errors.Wrapf(ErrInvalidConfig, "CNI config list %s has no networks, skipping", confFile) + return errors.Wrapf(ErrInvalidConfig, "CNI config list in config file %s has no networks, skipping", confFile) } networks = append(networks, &Network{ diff --git a/vendor/github.com/containerd/go-cni/result.go b/vendor/github.com/containerd/go-cni/result.go index 1e958dc76..c2ac94864 100644 --- a/vendor/github.com/containerd/go-cni/result.go +++ b/vendor/github.com/containerd/go-cni/result.go @@ -79,7 +79,7 @@ func (c *libcni) GetCNIResultFromResults(results []*current.Result) (*CNIResult, // interfaces for _, ipConf := range result.IPs { if err := validateInterfaceConfig(ipConf, len(result.Interfaces)); err != nil { - return nil, errors.Wrapf(ErrInvalidResult, "failed to valid interface config: %v", err) + return nil, errors.Wrapf(ErrInvalidResult, "invalid interface config: %v", err) } name := c.getInterfaceName(result.Interfaces, ipConf) r.Interfaces[name].IPConfigs = append(r.Interfaces[name].IPConfigs, @@ -89,7 +89,7 @@ func (c *libcni) GetCNIResultFromResults(results []*current.Result) (*CNIResult, r.Routes = append(r.Routes, result.Routes...) } if _, ok := r.Interfaces[defaultInterface(c.prefix)]; !ok { - return nil, errors.Wrapf(ErrNotFound, "default network not found") + return nil, errors.Wrapf(ErrNotFound, "default network not found for: %s", defaultInterface(c.prefix)) } return r, nil } diff --git a/vendor/github.com/containerd/go-cni/vendor.conf b/vendor/github.com/containerd/go-cni/vendor.conf index aefe9a108..31d06e0fc 100644 --- a/vendor/github.com/containerd/go-cni/vendor.conf +++ b/vendor/github.com/containerd/go-cni/vendor.conf @@ -2,5 +2,5 @@ github.com/stretchr/testify b89eecf5ca5db6d3ba60b237ffe3df7bafb7662f github.com/davecgh/go-spew 8991bc29aa16c548c550c7ff78260e27b9ab7c73 github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2 github.com/stretchr/objx 8a3f7159479fbc75b30357fbc48f380b7320f08e -github.com/containernetworking/cni 142cde0c766cd6055cc7fdfdcb44579c0c9c35bf +github.com/containernetworking/cni v0.7.1 github.com/pkg/errors v0.8.0 diff --git a/vendor/github.com/containernetworking/cni/README.md b/vendor/github.com/containernetworking/cni/README.md index 793187c79..4d300a10d 100644 --- a/vendor/github.com/containernetworking/cni/README.md +++ b/vendor/github.com/containernetworking/cni/README.md @@ -1,4 +1,5 @@ -[![Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/containernetworking/cni) +[![Linux Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/containernetworking/cni) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/wtrkou8oow7x533e/branch/master?svg=true)](https://ci.appveyor.com/project/cni-bot/cni/branch/master) [![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/containernetworking/cni?branch=master) [![Slack Status](https://cryptic-tundra-43194.herokuapp.com/badge.svg)](https://cryptic-tundra-43194.herokuapp.com/) @@ -8,7 +9,9 @@ # Community Sync Meeting -There is a community sync meeting for users and developers every 1-2 months. The next meeting will help on a Google Hangout and the link is in the [agenda](https://docs.google.com/document/d/10ECyT2mBGewsJUcmYmS8QNo1AcNgy2ZIe2xS7lShYhE/edit?usp=sharing) (Notes from previous meeting are also in this doc). The next meeting will be held on *Wednesday, June 21th* at *3:00pm UTC* [Add to Calendar]https://www.worldtimebuddy.com/?qm=1&lid=100,5,2643743,5391959&h=100&date=2017-6-21&sln=15-16). +There is a community sync meeting for users and developers every 1-2 months. The next meeting will help on a Google Hangout and the link is in the [agenda](https://docs.google.com/document/d/10ECyT2mBGewsJUcmYmS8QNo1AcNgy2ZIe2xS7lShYhE/edit?usp=sharing) (Notes from previous meeting are also in this doc). + +The next meeting will be held on *Wednesday, January 30th, 2019* at *4:00pm UTC / 11:00am EDT / 8:00am PDT* [Add to Calendar](https://www.worldtimebuddy.com/?qm=1&lid=100,5,2643743,5391959&h=100&date=2019-01-30&sln=16-17). --- @@ -35,11 +38,13 @@ To avoid duplication, we think it is prudent to define a common interface betwee ## Who is using CNI? ### Container runtimes - [rkt - container engine](https://coreos.com/blog/rkt-cni-networking.html) -- [Kurma - container runtime](http://kurma.io/) -- [Kubernetes - a system to simplify container operations](http://kubernetes.io/docs/admin/network-plugins/) +- [Kubernetes - a system to simplify container operations](https://kubernetes.io/docs/admin/network-plugins/) - [OpenShift - Kubernetes with additional enterprise features](https://github.com/openshift/origin/blob/master/docs/openshift_networking_requirements.md) - [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/cf-networking-release) -- [Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md) +- [Apache Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md) +- [Amazon ECS - a highly scalable, high performance container management service](https://aws.amazon.com/ecs/) +- [Singularity - container platform optimized for HPC, EPC, and AI](https://github.com/sylabs/singularity) +- [OpenSVC - orchestrator for legacy and containerized application stacks](https://docs.opensvc.com/latest/fr/agent.configure.cni.html) ### 3rd party plugins - [Project Calico - a layer 3 virtual network](https://github.com/projectcalico/calico-cni) @@ -54,6 +59,15 @@ To avoid duplication, we think it is prudent to define a common interface betwee - [Nuage CNI - Nuage Networks SDN plugin for network policy kubernetes support ](https://github.com/nuagenetworks/nuage-cni) - [Silk - a CNI plugin designed for Cloud Foundry](https://github.com/cloudfoundry-incubator/silk) - [Linen - a CNI plugin designed for overlay networks with Open vSwitch and fit in SDN/OpenFlow network environment](https://github.com/John-Lin/linen-cni) +- [Vhostuser - a Dataplane network plugin - Supports OVS-DPDK & VPP](https://github.com/intel/vhost-user-net-plugin) +- [Amazon ECS CNI Plugins - a collection of CNI Plugins to configure containers with Amazon EC2 elastic network interfaces (ENIs)](https://github.com/aws/amazon-ecs-cni-plugins) +- [Bonding CNI - a Link aggregating plugin to address failover and high availability network](https://github.com/Intel-Corp/bond-cni) +- [ovn-kubernetes - an container network plugin built on Open vSwitch (OVS) and Open Virtual Networking (OVN) with support for both Linux and Windows](https://github.com/openvswitch/ovn-kubernetes) +- [Juniper Contrail](https://www.juniper.net/cloud) / [TungstenFabric](https://tungstenfabric.io) - Provides overlay SDN solution, delivering multicloud networking, hybrid cloud networking, simultaneous overlay-underlay support, network policy enforcement, network isolation, service chaining and flexible load balancing +- [Knitter - a CNI plugin supporting multiple networking for Kubernetes](https://github.com/ZTE/Knitter) +- [DANM - a CNI-compliant networking solution for TelCo workloads running on Kubernetes](https://github.com/nokia/danm) +- [VMware NSX – a CNI plugin that enables automated NSX L2/L3 networking and L4/L7 Load Balancing; network isolation at the pod, node, and cluster level; and zero-trust security policy for your Kubernetes cluster.](https://docs.vmware.com/en/VMware-NSX-T/2.2/com.vmware.nsxt.ncp_kubernetes.doc/GUID-6AFA724E-BB62-4693-B95C-321E8DDEA7E1.html) +- [cni-route-override - a meta CNI plugin that override route information](https://github.com/redhat-nfvpe/cni-route-override) The CNI team also maintains some [core plugins in a separate repository](https://github.com/containernetworking/plugins). @@ -67,7 +81,7 @@ If you intend to contribute to code or documentation, please read [CONTRIBUTING. ### Requirements -The CNI spec is language agnostic. To use the Go language libraries in this repository, you'll need a recent version of Go. Our [automated tests](https://travis-ci.org/containernetworking/cni/builds) cover Go versions 1.7 and 1.8. +The CNI spec is language agnostic. To use the Go language libraries in this repository, you'll need a recent version of Go. You can find the Go versions covered by our [automated tests](https://travis-ci.org/containernetworking/cni/builds) in [.travis.yaml](.travis.yml). ### Reference Plugins @@ -104,6 +118,7 @@ EOF $ cat >/etc/cni/net.d/99-loopback.conf <= 0; i-- { - net := list.Plugins[i] +func (c *CNIConfig) checkNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error { + c.ensureExec() + pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path) + if err != nil { + return err + } - pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path) - if err != nil { - return err - } + newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) + if err != nil { + return err + } - newConf, err := buildOneConfig(list, net, nil, rt) - if err != nil { - return err - } + return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("CHECK", rt), c.exec) +} - if err := invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt)); err != nil { +// CheckNetworkList executes a sequence of plugins with the CHECK command +func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error { + // CHECK was added in CNI spec version 0.4.0 and higher + if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil { + return err + } else if !gtet { + return fmt.Errorf("configuration version %q does not support the CHECK command", list.CNIVersion) + } + + if list.DisableCheck { + return nil + } + + cachedResult, err := getCachedResult(list.Name, list.CNIVersion, rt) + if err != nil { + return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) + } + + for _, net := range list.Plugins { + if err := c.checkNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil { return err } } @@ -165,45 +309,179 @@ func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) err return nil } +func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error { + c.ensureExec() + pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path) + if err != nil { + return err + } + + newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) + if err != nil { + return err + } + + return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("DEL", rt), c.exec) +} + +// DelNetworkList executes a sequence of plugins with the DEL command +func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error { + var cachedResult types.Result + + // Cached result on DEL was added in CNI spec version 0.4.0 and higher + if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil { + return err + } else if gtet { + cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt) + if err != nil { + return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) + } + } + + for i := len(list.Plugins) - 1; i >= 0; i-- { + net := list.Plugins[i] + if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil { + return err + } + } + _ = delCachedResult(list.Name, rt) + + return nil +} + // AddNetwork executes the plugin with the ADD command -func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { - pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path) +func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { + result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt) if err != nil { return nil, err } - net, err = injectRuntimeConfig(net, rt) - if err != nil { - return nil, err + if err = setCachedResult(result, net.Network.Name, rt); err != nil { + return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err) } - return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt)) + return result, nil +} + +// CheckNetwork executes the plugin with the CHECK command +func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error { + // CHECK was added in CNI spec version 0.4.0 and higher + if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil { + return err + } else if !gtet { + return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion) + } + + cachedResult, err := getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) + if err != nil { + return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) + } + return c.checkNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt) } // DelNetwork executes the plugin with the DEL command -func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error { - pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path) +func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error { + var cachedResult types.Result + + // Cached result on DEL was added in CNI spec version 0.4.0 and higher + if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil { + return err + } else if gtet { + cachedResult, err = getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) + if err != nil { + return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) + } + } + + if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil { + return err + } + _ = delCachedResult(net.Network.Name, rt) + return nil +} + +// ValidateNetworkList checks that a configuration is reasonably valid. +// - all the specified plugins exist on disk +// - every plugin supports the desired version. +// +// Returns a list of all capabilities supported by the configuration, or error +func (c *CNIConfig) ValidateNetworkList(ctx context.Context, list *NetworkConfigList) ([]string, error) { + version := list.CNIVersion + + // holding map for seen caps (in case of duplicates) + caps := map[string]interface{}{} + + errs := []error{} + for _, net := range list.Plugins { + if err := c.validatePlugin(ctx, net.Network.Type, version); err != nil { + errs = append(errs, err) + } + for c, enabled := range net.Network.Capabilities { + if !enabled { + continue + } + caps[c] = struct{}{} + } + } + + if len(errs) > 0 { + return nil, fmt.Errorf("%v", errs) + } + + // make caps list + cc := make([]string, 0, len(caps)) + for c := range caps { + cc = append(cc, c) + } + + return cc, nil +} + +// ValidateNetwork checks that a configuration is reasonably valid. +// It uses the same logic as ValidateNetworkList) +// Returns a list of capabilities +func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) { + caps := []string{} + for c, ok := range net.Network.Capabilities { + if ok { + caps = append(caps, c) + } + } + if err := c.validatePlugin(ctx, net.Network.Type, net.Network.CNIVersion); err != nil { + return nil, err + } + return caps, nil +} + +// validatePlugin checks that an individual plugin's configuration is sane +func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error { + pluginPath, err := invoke.FindInPath(pluginName, c.Path) if err != nil { return err } - net, err = injectRuntimeConfig(net, rt) + vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec) if err != nil { return err } - - return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt)) + for _, vers := range vi.SupportedVersions() { + if vers == expectedVersion { + return nil + } + } + return fmt.Errorf("plugin %s does not support config version %q", pluginName, expectedVersion) } // GetVersionInfo reports which versions of the CNI spec are supported by // the given plugin. -func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) { - pluginPath, err := invoke.FindInPath(pluginType, c.Path) +func (c *CNIConfig) GetVersionInfo(ctx context.Context, pluginType string) (version.PluginInfo, error) { + c.ensureExec() + pluginPath, err := c.exec.FindInPath(pluginType, c.Path) if err != nil { return nil, err } - return invoke.GetVersionInfo(pluginPath) + return invoke.GetVersionInfo(ctx, pluginPath, c.exec) } // ===== diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go index c7738c665..ea56c509d 100644 --- a/vendor/github.com/containernetworking/cni/libcni/conf.go +++ b/vendor/github.com/containernetworking/cni/libcni/conf.go @@ -45,6 +45,9 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) { if err := json.Unmarshal(bytes, &conf.Network); err != nil { return nil, fmt.Errorf("error parsing configuration: %s", err) } + if conf.Network.Type == "" { + return nil, fmt.Errorf("error parsing configuration: missing 'type'") + } return conf, nil } @@ -80,10 +83,19 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) { } } + disableCheck := false + if rawDisableCheck, ok := rawList["disableCheck"]; ok { + disableCheck, ok = rawDisableCheck.(bool) + if !ok { + return nil, fmt.Errorf("error parsing configuration list: invalid disableCheck type %T", rawDisableCheck) + } + } + list := &NetworkConfigList{ - Name: name, - CNIVersion: cniVersion, - Bytes: bytes, + Name: name, + DisableCheck: disableCheck, + CNIVersion: cniVersion, + Bytes: bytes, } var plugins []interface{} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go index 39b639723..913528c1d 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go @@ -15,6 +15,7 @@ package invoke import ( + "fmt" "os" "strings" ) @@ -22,6 +23,8 @@ import ( type CNIArgs interface { // For use with os/exec; i.e., return nil to inherit the // environment from this process + // For use in delegation; inherit the environment from this + // process and allow overrides AsEnv() []string } @@ -57,17 +60,17 @@ func (args *Args) AsEnv() []string { pluginArgsStr = stringify(args.PluginArgs) } - // Ensure that the custom values are first, so any value present in - // the process environment won't override them. - env = append([]string{ - "CNI_COMMAND=" + args.Command, - "CNI_CONTAINERID=" + args.ContainerID, - "CNI_NETNS=" + args.NetNS, - "CNI_ARGS=" + pluginArgsStr, - "CNI_IFNAME=" + args.IfName, - "CNI_PATH=" + args.Path, - }, env...) - return env + // Duplicated values which come first will be overrided, so we must put the + // custom values in the end to avoid being overrided by the process environments. + env = append(env, + "CNI_COMMAND="+args.Command, + "CNI_CONTAINERID="+args.ContainerID, + "CNI_NETNS="+args.NetNS, + "CNI_ARGS="+pluginArgsStr, + "CNI_IFNAME="+args.IfName, + "CNI_PATH="+args.Path, + ) + return dedupEnv(env) } // taken from rkt/networking/net_plugin.go @@ -80,3 +83,46 @@ func stringify(pluginArgs [][2]string) string { return strings.Join(entries, ";") } + +// DelegateArgs implements the CNIArgs interface +// used for delegation to inherit from environments +// and allow some overrides like CNI_COMMAND +var _ CNIArgs = &DelegateArgs{} + +type DelegateArgs struct { + Command string +} + +func (d *DelegateArgs) AsEnv() []string { + env := os.Environ() + + // The custom values should come in the end to override the existing + // process environment of the same key. + env = append(env, + "CNI_COMMAND="+d.Command, + ) + return dedupEnv(env) +} + +// dedupEnv returns a copy of env with any duplicates removed, in favor of later values. +// Items not of the normal environment "key=value" form are preserved unchanged. +func dedupEnv(env []string) []string { + out := make([]string, 0, len(env)) + envMap := map[string]string{} + + for _, kv := range env { + // find the first "=" in environment, if not, just keep it + eq := strings.Index(kv, "=") + if eq < 0 { + out = append(out, kv) + continue + } + envMap[kv[:eq]] = kv[eq+1:] + } + + for k, v := range envMap { + out = append(out, fmt.Sprintf("%s=%s", k, v)) + } + + return out +} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go index c78a69eeb..8defe4dd3 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go @@ -15,39 +15,66 @@ package invoke import ( - "fmt" + "context" "os" "path/filepath" "github.com/containernetworking/cni/pkg/types" ) -func DelegateAdd(delegatePlugin string, netconf []byte) (types.Result, error) { - if os.Getenv("CNI_COMMAND") != "ADD" { - return nil, fmt.Errorf("CNI_COMMAND is not ADD") +func delegateCommon(delegatePlugin string, exec Exec) (string, Exec, error) { + if exec == nil { + exec = defaultExec } paths := filepath.SplitList(os.Getenv("CNI_PATH")) + pluginPath, err := exec.FindInPath(delegatePlugin, paths) + if err != nil { + return "", nil, err + } - pluginPath, err := FindInPath(delegatePlugin, paths) + return pluginPath, exec, nil +} + +// DelegateAdd calls the given delegate plugin with the CNI ADD action and +// JSON configuration +func DelegateAdd(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) { + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) if err != nil { return nil, err } - return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv()) + // DelegateAdd will override the original "CNI_COMMAND" env from process with ADD + return ExecPluginWithResult(ctx, pluginPath, netconf, delegateArgs("ADD"), realExec) } -func DelegateDel(delegatePlugin string, netconf []byte) error { - if os.Getenv("CNI_COMMAND") != "DEL" { - return fmt.Errorf("CNI_COMMAND is not DEL") - } - - paths := filepath.SplitList(os.Getenv("CNI_PATH")) - - pluginPath, err := FindInPath(delegatePlugin, paths) +// DelegateCheck calls the given delegate plugin with the CNI CHECK action and +// JSON configuration +func DelegateCheck(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) if err != nil { return err } - return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv()) + // DelegateCheck will override the original CNI_COMMAND env from process with CHECK + return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("CHECK"), realExec) +} + +// DelegateDel calls the given delegate plugin with the CNI DEL action and +// JSON configuration +func DelegateDel(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) + if err != nil { + return err + } + + // DelegateDel will override the original CNI_COMMAND env from process with DEL + return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("DEL"), realExec) +} + +// return CNIArgs used by delegation +func delegateArgs(action string) *DelegateArgs { + return &DelegateArgs{ + Command: action, + } } diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go index fc47e7c82..8e6d30b82 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go @@ -15,6 +15,7 @@ package invoke import ( + "context" "fmt" "os" @@ -22,34 +23,62 @@ import ( "github.com/containernetworking/cni/pkg/version" ) -func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) { - return defaultPluginExec.WithResult(pluginPath, netconf, args) +// Exec is an interface encapsulates all operations that deal with finding +// and executing a CNI plugin. Tests may provide a fake implementation +// to avoid writing fake plugins to temporary directories during the test. +type Exec interface { + ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) + FindInPath(plugin string, paths []string) (string, error) + Decode(jsonBytes []byte) (version.PluginInfo, error) } -func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error { - return defaultPluginExec.WithoutResult(pluginPath, netconf, args) -} +// For example, a testcase could pass an instance of the following fakeExec +// object to ExecPluginWithResult() to verify the incoming stdin and environment +// and provide a tailored response: +// +//import ( +// "encoding/json" +// "path" +// "strings" +//) +// +//type fakeExec struct { +// version.PluginDecoder +//} +// +//func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) { +// net := &types.NetConf{} +// err := json.Unmarshal(stdinData, net) +// if err != nil { +// return nil, fmt.Errorf("failed to unmarshal configuration: %v", err) +// } +// pluginName := path.Base(pluginPath) +// if pluginName != net.Type { +// return nil, fmt.Errorf("plugin name %q did not match config type %q", pluginName, net.Type) +// } +// for _, e := range environ { +// // Check environment for forced failure request +// parts := strings.Split(e, "=") +// if len(parts) > 0 && parts[0] == "FAIL" { +// return nil, fmt.Errorf("failed to execute plugin %s", pluginName) +// } +// } +// return []byte("{\"CNIVersion\":\"0.4.0\"}"), nil +//} +// +//func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) { +// if len(paths) > 0 { +// return path.Join(paths[0], plugin), nil +// } +// return "", fmt.Errorf("failed to find plugin %s in paths %v", plugin, paths) +//} -func GetVersionInfo(pluginPath string) (version.PluginInfo, error) { - return defaultPluginExec.GetVersionInfo(pluginPath) -} - -var defaultPluginExec = &PluginExec{ - RawExec: &RawExec{Stderr: os.Stderr}, - VersionDecoder: &version.PluginDecoder{}, -} - -type PluginExec struct { - RawExec interface { - ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) +func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) { + if exec == nil { + exec = defaultExec } - VersionDecoder interface { - Decode(jsonBytes []byte) (version.PluginInfo, error) - } -} -func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) { - stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv()) + stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv()) if err != nil { return nil, err } @@ -64,8 +93,11 @@ func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) return version.NewResult(confVersion, stdoutBytes) } -func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error { - _, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv()) +func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error { + if exec == nil { + exec = defaultExec + } + _, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv()) return err } @@ -73,7 +105,10 @@ func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIAr // For recent-enough plugins, it uses the information returned by the VERSION // command. For older plugins which do not recognize that command, it reports // version 0.1.0 -func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, error) { +func GetVersionInfo(ctx context.Context, pluginPath string, exec Exec) (version.PluginInfo, error) { + if exec == nil { + exec = defaultExec + } args := &Args{ Command: "VERSION", @@ -83,7 +118,7 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro Path: "dummy", } stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current())) - stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, stdin, args.AsEnv()) + stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, stdin, args.AsEnv()) if err != nil { if err.Error() == "unknown CNI_COMMAND: VERSION" { return version.PluginSupports("0.1.0"), nil @@ -91,5 +126,19 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro return nil, err } - return e.VersionDecoder.Decode(stdoutBytes) + return exec.Decode(stdoutBytes) +} + +// DefaultExec is an object that implements the Exec interface which looks +// for and executes plugins from disk. +type DefaultExec struct { + *RawExec + version.PluginDecoder +} + +// DefaultExec implements the Exec interface +var _ Exec = &DefaultExec{} + +var defaultExec = &DefaultExec{ + RawExec: &RawExec{Stderr: os.Stderr}, } diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go index bab5737a9..9bcfb4553 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build darwin dragonfly freebsd linux netbsd opensbd solaris +// +build darwin dragonfly freebsd linux netbsd openbsd solaris package invoke diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go index 93f1e75d9..ad8498ba2 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go @@ -16,6 +16,7 @@ package invoke import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -28,17 +29,13 @@ type RawExec struct { Stderr io.Writer } -func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) { +func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) { stdout := &bytes.Buffer{} - - c := exec.Cmd{ - Env: environ, - Path: pluginPath, - Args: []string{pluginPath}, - Stdin: bytes.NewBuffer(stdinData), - Stdout: stdout, - Stderr: e.Stderr, - } + c := exec.CommandContext(ctx, pluginPath) + c.Env = environ + c.Stdin = bytes.NewBuffer(stdinData) + c.Stdout = stdout + c.Stderr = e.Stderr if err := c.Run(); err != nil { return nil, pluginErr(err, stdout.Bytes()) } @@ -49,7 +46,9 @@ func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []stri func pluginErr(err error, output []byte) error { if _, ok := err.(*exec.ExitError); ok { emsg := types.Error{} - if perr := json.Unmarshal(output, &emsg); perr != nil { + if len(output) == 0 { + emsg.Msg = "netplugin failed with no error message" + } else if perr := json.Unmarshal(output, &emsg); perr != nil { emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr) } return &emsg @@ -57,3 +56,7 @@ func pluginErr(err error, output []byte) error { return err } + +func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) { + return FindInPath(plugin, paths) +} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go index 2833aba78..53256167f 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go @@ -17,6 +17,7 @@ package types020 import ( "encoding/json" "fmt" + "io" "net" "os" @@ -73,11 +74,15 @@ func (r *Result) GetAsVersion(version string) (types.Result, error) { } func (r *Result) Print() error { + return r.PrintTo(os.Stdout) +} + +func (r *Result) PrintTo(writer io.Writer) error { data, err := json.MarshalIndent(r, "", " ") if err != nil { return err } - _, err = os.Stdout.Write(data) + _, err = writer.Write(data) return err } diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go index caac92ba7..7267a2e6d 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go @@ -17,6 +17,7 @@ package current import ( "encoding/json" "fmt" + "io" "net" "os" @@ -24,9 +25,9 @@ import ( "github.com/containernetworking/cni/pkg/types/020" ) -const ImplementedSpecVersion string = "0.3.1" +const ImplementedSpecVersion string = "0.4.0" -var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion} +var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion} func NewResult(data []byte) (types.Result, error) { result := &Result{} @@ -75,13 +76,9 @@ func convertFrom020(result types.Result) (*Result, error) { Gateway: oldResult.IP4.Gateway, }) for _, route := range oldResult.IP4.Routes { - gw := route.GW - if gw == nil { - gw = oldResult.IP4.Gateway - } newResult.Routes = append(newResult.Routes, &types.Route{ Dst: route.Dst, - GW: gw, + GW: route.GW, }) } } @@ -93,21 +90,13 @@ func convertFrom020(result types.Result) (*Result, error) { Gateway: oldResult.IP6.Gateway, }) for _, route := range oldResult.IP6.Routes { - gw := route.GW - if gw == nil { - gw = oldResult.IP6.Gateway - } newResult.Routes = append(newResult.Routes, &types.Route{ Dst: route.Dst, - GW: gw, + GW: route.GW, }) } } - if len(newResult.IPs) == 0 { - return nil, fmt.Errorf("cannot convert: no valid IP addresses") - } - return newResult, nil } @@ -196,7 +185,7 @@ func (r *Result) Version() string { func (r *Result) GetAsVersion(version string) (types.Result, error) { switch version { - case "0.3.0", ImplementedSpecVersion: + case "0.3.0", "0.3.1", ImplementedSpecVersion: r.CNIVersion = version return r, nil case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]: @@ -206,11 +195,15 @@ func (r *Result) GetAsVersion(version string) (types.Result, error) { } func (r *Result) Print() error { + return r.PrintTo(os.Stdout) +} + +func (r *Result) PrintTo(writer io.Writer) error { data, err := json.MarshalIndent(r, "", " ") if err != nil { return err } - _, err = os.Stdout.Write(data) + _, err = writer.Write(data) return err } diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go index 641275600..d0d11006a 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go @@ -18,6 +18,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net" "os" ) @@ -63,25 +64,31 @@ type NetConf struct { Name string `json:"name,omitempty"` Type string `json:"type,omitempty"` Capabilities map[string]bool `json:"capabilities,omitempty"` - IPAM struct { - Type string `json:"type,omitempty"` - } `json:"ipam,omitempty"` - DNS DNS `json:"dns"` + IPAM IPAM `json:"ipam,omitempty"` + DNS DNS `json:"dns"` + + RawPrevResult map[string]interface{} `json:"prevResult,omitempty"` + PrevResult Result `json:"-"` +} + +type IPAM struct { + Type string `json:"type,omitempty"` } // NetConfList describes an ordered list of networks. type NetConfList struct { CNIVersion string `json:"cniVersion,omitempty"` - Name string `json:"name,omitempty"` - Plugins []*NetConf `json:"plugins,omitempty"` + Name string `json:"name,omitempty"` + DisableCheck bool `json:"disableCheck,omitempty"` + Plugins []*NetConf `json:"plugins,omitempty"` } type ResultFactoryFunc func([]byte) (Result, error) // Result is an interface that provides the result of plugin execution type Result interface { - // The highest CNI specification result verison the result supports + // The highest CNI specification result version the result supports // without having to convert Version() string @@ -92,6 +99,9 @@ type Result interface { // Prints the result in JSON format to stdout Print() error + // Prints the result in JSON format to provided writer + PrintTo(writer io.Writer) error + // Returns a JSON string representation of the result String() string } @@ -167,7 +177,7 @@ func (r *Route) UnmarshalJSON(data []byte) error { return nil } -func (r *Route) MarshalJSON() ([]byte, error) { +func (r Route) MarshalJSON() ([]byte, error) { rt := route{ Dst: IPNet(r.Dst), GW: r.GW, diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go index 8a4672810..1df427243 100644 --- a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go +++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go @@ -18,6 +18,8 @@ import ( "encoding/json" "fmt" "io" + "strconv" + "strings" ) // PluginInfo reports information about CNI versioning @@ -79,3 +81,64 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) { } return &info, nil } + +// ParseVersion parses a version string like "3.0.1" or "0.4.5" into major, +// minor, and micro numbers or returns an error +func ParseVersion(version string) (int, int, int, error) { + var major, minor, micro int + if version == "" { + return -1, -1, -1, fmt.Errorf("invalid version %q: the version is empty", version) + } + + parts := strings.Split(version, ".") + if len(parts) >= 4 { + return -1, -1, -1, fmt.Errorf("invalid version %q: too many parts", version) + } + + major, err := strconv.Atoi(parts[0]) + if err != nil { + return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err) + } + + if len(parts) >= 2 { + minor, err = strconv.Atoi(parts[1]) + if err != nil { + return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err) + } + } + + if len(parts) >= 3 { + micro, err = strconv.Atoi(parts[2]) + if err != nil { + return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err) + } + } + + return major, minor, micro, nil +} + +// GreaterThanOrEqualTo takes two string versions, parses them into major/minor/micro +// numbers, and compares them to determine whether the first version is greater +// than or equal to the second +func GreaterThanOrEqualTo(version, otherVersion string) (bool, error) { + firstMajor, firstMinor, firstMicro, err := ParseVersion(version) + if err != nil { + return false, err + } + + secondMajor, secondMinor, secondMicro, err := ParseVersion(otherVersion) + if err != nil { + return false, err + } + + if firstMajor > secondMajor { + return true, nil + } else if firstMajor == secondMajor { + if firstMinor > secondMinor { + return true, nil + } else if firstMinor == secondMinor && firstMicro >= secondMicro { + return true, nil + } + } + return false, nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go index efe8ea871..8f3508e61 100644 --- a/vendor/github.com/containernetworking/cni/pkg/version/version.go +++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go @@ -15,6 +15,7 @@ package version import ( + "encoding/json" "fmt" "github.com/containernetworking/cni/pkg/types" @@ -24,7 +25,7 @@ import ( // Current reports the version of the CNI spec implemented by this library func Current() string { - return "0.3.1" + return "0.4.0" } // Legacy PluginInfo describes a plugin that is backwards compatible with the @@ -35,7 +36,7 @@ func Current() string { // Any future CNI spec versions which meet this definition should be added to // this list. var Legacy = PluginSupports("0.1.0", "0.2.0") -var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1") +var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0") var resultFactories = []struct { supportedVersions []string @@ -59,3 +60,24 @@ func NewResult(version string, resultBytes []byte) (types.Result, error) { return nil, fmt.Errorf("unsupported CNI result version %q", version) } + +// ParsePrevResult parses a prevResult in a NetConf structure and sets +// the NetConf's PrevResult member to the parsed Result object. +func ParsePrevResult(conf *types.NetConf) error { + if conf.RawPrevResult == nil { + return nil + } + + resultBytes, err := json.Marshal(conf.RawPrevResult) + if err != nil { + return fmt.Errorf("could not serialize prevResult: %v", err) + } + + conf.RawPrevResult = nil + conf.PrevResult, err = NewResult(conf.CNIVersion, resultBytes) + if err != nil { + return fmt.Errorf("could not parse prevResult: %v", err) + } + + return nil +} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE index c83641619..bc52e96f2 100644 --- a/vendor/github.com/davecgh/go-spew/LICENSE +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -2,7 +2,7 @@ ISC License Copyright (c) 2012-2016 Dave Collins -Permission to use, copy, modify, and distribute this software for any +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff --git a/vendor/github.com/davecgh/go-spew/README.md b/vendor/github.com/davecgh/go-spew/README.md index 262430449..f6ed02c3b 100644 --- a/vendor/github.com/davecgh/go-spew/README.md +++ b/vendor/github.com/davecgh/go-spew/README.md @@ -1,12 +1,9 @@ go-spew ======= -[![Build Status](https://img.shields.io/travis/davecgh/go-spew.svg)] -(https://travis-ci.org/davecgh/go-spew) [![ISC License] -(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![Coverage Status] -(https://img.shields.io/coveralls/davecgh/go-spew.svg)] -(https://coveralls.io/r/davecgh/go-spew?branch=master) - +[![Build Status](https://img.shields.io/travis/davecgh/go-spew.svg)](https://travis-ci.org/davecgh/go-spew) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![Coverage Status](https://img.shields.io/coveralls/davecgh/go-spew.svg)](https://coveralls.io/r/davecgh/go-spew?branch=master) Go-spew implements a deep pretty printer for Go data structures to aid in debugging. A comprehensive suite of tests with 100% test coverage is provided @@ -21,8 +18,7 @@ post about it ## Documentation -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)] -(http://godoc.org/github.com/davecgh/go-spew/spew) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/davecgh/go-spew/spew) Full `go doc` style documentation for the project can be viewed online without installing this package by using the excellent GoDoc site here: diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go index 8a4a6589a..792994785 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -16,7 +16,9 @@ // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build !js,!appengine,!safe,!disableunsafe +// Go versions prior to 1.4 are disabled because they use a different layout +// for interfaces which make the implementation of unsafeReflectValue more complex. +// +build !js,!appengine,!safe,!disableunsafe,go1.4 package spew @@ -34,80 +36,49 @@ const ( ptrSize = unsafe.Sizeof((*byte)(nil)) ) -var ( - // offsetPtr, offsetScalar, and offsetFlag are the offsets for the - // internal reflect.Value fields. These values are valid before golang - // commit ecccf07e7f9d which changed the format. The are also valid - // after commit 82f48826c6c7 which changed the format again to mirror - // the original format. Code in the init function updates these offsets - // as necessary. - offsetPtr = uintptr(ptrSize) - offsetScalar = uintptr(0) - offsetFlag = uintptr(ptrSize * 2) +type flag uintptr - // flagKindWidth and flagKindShift indicate various bits that the - // reflect package uses internally to track kind information. - // - // flagRO indicates whether or not the value field of a reflect.Value is - // read-only. - // - // flagIndir indicates whether the value field of a reflect.Value is - // the actual data or a pointer to the data. - // - // These values are valid before golang commit 90a7c3c86944 which - // changed their positions. Code in the init function updates these - // flags as necessary. - flagKindWidth = uintptr(5) - flagKindShift = uintptr(flagKindWidth - 1) - flagRO = uintptr(1 << 0) - flagIndir = uintptr(1 << 1) +var ( + // flagRO indicates whether the value field of a reflect.Value + // is read-only. + flagRO flag + + // flagAddr indicates whether the address of the reflect.Value's + // value may be taken. + flagAddr flag ) -func init() { - // Older versions of reflect.Value stored small integers directly in the - // ptr field (which is named val in the older versions). Versions - // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named - // scalar for this purpose which unfortunately came before the flag - // field, so the offset of the flag field is different for those - // versions. - // - // This code constructs a new reflect.Value from a known small integer - // and checks if the size of the reflect.Value struct indicates it has - // the scalar field. When it does, the offsets are updated accordingly. - vv := reflect.ValueOf(0xf00) - if unsafe.Sizeof(vv) == (ptrSize * 4) { - offsetScalar = ptrSize * 2 - offsetFlag = ptrSize * 3 - } +// flagKindMask holds the bits that make up the kind +// part of the flags field. In all the supported versions, +// it is in the lower 5 bits. +const flagKindMask = flag(0x1f) - // Commit 90a7c3c86944 changed the flag positions such that the low - // order bits are the kind. This code extracts the kind from the flags - // field and ensures it's the correct type. When it's not, the flag - // order has been changed to the newer format, so the flags are updated - // accordingly. - upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) - upfv := *(*uintptr)(upf) - flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { - flagKindShift = 0 - flagRO = 1 << 5 - flagIndir = 1 << 6 +// Different versions of Go have used different +// bit layouts for the flags type. This table +// records the known combinations. +var okFlags = []struct { + ro, addr flag +}{{ + // From Go 1.4 to 1.5 + ro: 1 << 5, + addr: 1 << 7, +}, { + // Up to Go tip. + ro: 1<<5 | 1<<6, + addr: 1 << 8, +}} - // Commit adf9b30e5594 modified the flags to separate the - // flagRO flag into two bits which specifies whether or not the - // field is embedded. This causes flagIndir to move over a bit - // and means that flagRO is the combination of either of the - // original flagRO bit and the new bit. - // - // This code detects the change by extracting what used to be - // the indirect bit to ensure it's set. When it's not, the flag - // order has been changed to the newer format, so the flags are - // updated accordingly. - if upfv&flagIndir == 0 { - flagRO = 3 << 5 - flagIndir = 1 << 7 - } +var flagValOffset = func() uintptr { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") } + return field.Offset +}() + +// flagField returns a pointer to the flag field of a reflect.Value. +func flagField(v *reflect.Value) *flag { + return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses @@ -119,34 +90,56 @@ func init() { // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { - indirects := 1 - vt := v.Type() - upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) - rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) - if rvf&flagIndir != 0 { - vt = reflect.PtrTo(v.Type()) - indirects++ - } else if offsetScalar != 0 { - // The value is in the scalar field when it's not one of the - // reference types. - switch vt.Kind() { - case reflect.Uintptr: - case reflect.Chan: - case reflect.Func: - case reflect.Map: - case reflect.Ptr: - case reflect.UnsafePointer: - default: - upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + - offsetScalar) +func unsafeReflectValue(v reflect.Value) reflect.Value { + if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { + return v + } + flagFieldPtr := flagField(&v) + *flagFieldPtr &^= flagRO + *flagFieldPtr |= flagAddr + return v +} + +// Sanity checks against future reflect package changes +// to the type or semantics of the Value.flag field. +func init() { + field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") + if !ok { + panic("reflect.Value has no flag field") + } + if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { + panic("reflect.Value flag field has changed kind") + } + type t0 int + var t struct { + A t0 + // t0 will have flagEmbedRO set. + t0 + // a will have flagStickyRO set + a t0 + } + vA := reflect.ValueOf(t).FieldByName("A") + va := reflect.ValueOf(t).FieldByName("a") + vt0 := reflect.ValueOf(t).FieldByName("t0") + + // Infer flagRO from the difference between the flags + // for the (otherwise identical) fields in t. + flagPublic := *flagField(&vA) + flagWithRO := *flagField(&va) | *flagField(&vt0) + flagRO = flagPublic ^ flagWithRO + + // Infer flagAddr from the difference between a value + // taken from a pointer and not. + vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") + flagNoPtr := *flagField(&vA) + flagPtr := *flagField(&vPtrA) + flagAddr = flagNoPtr ^ flagPtr + + // Check that the inferred flags tally with one of the known versions. + for _, f := range okFlags { + if flagRO == f.ro && flagAddr == f.addr { + return } } - - pv := reflect.NewAt(vt, upv) - rv = pv - for i := 0; i < indirects; i++ { - rv = rv.Elem() - } - return rv + panic("reflect.Value read-only flag has changed semantics") } diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go index 1fe3cf3d5..205c28d68 100644 --- a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -16,7 +16,7 @@ // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe +// +build js appengine safe disableunsafe !go1.4 package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go index 7c519ff47..1be8ce945 100644 --- a/vendor/github.com/davecgh/go-spew/spew/common.go +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) { w.Write(closeParenBytes) } -// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go index df1d582a7..f78d89fc1 100644 --- a/vendor/github.com/davecgh/go-spew/spew/dump.go +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -35,16 +35,16 @@ var ( // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. - cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") + cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) ) // dumpState contains information about the state of a dump operation. @@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) { // Display dereferenced value. d.w.Write(openParenBytes) switch { - case nilFound == true: + case nilFound: d.w.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: d.w.Write(circularBytes) default: diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go index c49875bac..b04edb7d7 100644 --- a/vendor/github.com/davecgh/go-spew/spew/format.go +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) { // Display dereferenced value. switch { - case nilFound == true: + case nilFound: f.fs.Write(nilAngleBytes) - case cycleFound == true: + case cycleFound: f.fs.Write(circularShortBytes) default: diff --git a/vendor/github.com/google/gofuzz/fuzz.go b/vendor/github.com/google/gofuzz/fuzz.go index 4f888fbc8..1dfa80a6f 100644 --- a/vendor/github.com/google/gofuzz/fuzz.go +++ b/vendor/github.com/google/gofuzz/fuzz.go @@ -34,21 +34,27 @@ type Fuzzer struct { nilChance float64 minElements int maxElements int + maxDepth int } // New returns a new Fuzzer. Customize your Fuzzer further by calling Funcs, // RandSource, NilChance, or NumElements in any order. func New() *Fuzzer { + return NewWithSeed(time.Now().UnixNano()) +} + +func NewWithSeed(seed int64) *Fuzzer { f := &Fuzzer{ defaultFuzzFuncs: fuzzFuncMap{ reflect.TypeOf(&time.Time{}): reflect.ValueOf(fuzzTime), }, fuzzFuncs: fuzzFuncMap{}, - r: rand.New(rand.NewSource(time.Now().UnixNano())), + r: rand.New(rand.NewSource(seed)), nilChance: .2, minElements: 1, maxElements: 10, + maxDepth: 100, } return f } @@ -136,6 +142,14 @@ func (f *Fuzzer) genShouldFill() bool { return f.r.Float64() > f.nilChance } +// MaxDepth sets the maximum number of recursive fuzz calls that will be made +// before stopping. This includes struct members, pointers, and map and slice +// elements. +func (f *Fuzzer) MaxDepth(d int) *Fuzzer { + f.maxDepth = d + return f +} + // Fuzz recursively fills all of obj's fields with something random. First // this tries to find a custom fuzz function (see Funcs). If there is no // custom function this tests whether the object implements fuzz.Interface and, @@ -144,17 +158,19 @@ func (f *Fuzzer) genShouldFill() bool { // fails, this will generate random values for all primitive fields and then // recurse for all non-primitives. // -// Not safe for cyclic or tree-like structs! +// This is safe for cyclic or tree-like structs, up to a limit. Use the +// MaxDepth method to adjust how deep you need it to recurse. // -// obj must be a pointer. Only exported (public) fields can be set (thanks, golang :/ ) -// Intended for tests, so will panic on bad input or unimplemented fields. +// obj must be a pointer. Only exported (public) fields can be set (thanks, +// golang :/ ) Intended for tests, so will panic on bad input or unimplemented +// fields. func (f *Fuzzer) Fuzz(obj interface{}) { v := reflect.ValueOf(obj) if v.Kind() != reflect.Ptr { panic("needed ptr!") } v = v.Elem() - f.doFuzz(v, 0) + f.fuzzWithContext(v, 0) } // FuzzNoCustom is just like Fuzz, except that any custom fuzz function for @@ -170,7 +186,7 @@ func (f *Fuzzer) FuzzNoCustom(obj interface{}) { panic("needed ptr!") } v = v.Elem() - f.doFuzz(v, flagNoCustomFuzz) + f.fuzzWithContext(v, flagNoCustomFuzz) } const ( @@ -178,69 +194,87 @@ const ( flagNoCustomFuzz uint64 = 1 << iota ) -func (f *Fuzzer) doFuzz(v reflect.Value, flags uint64) { +func (f *Fuzzer) fuzzWithContext(v reflect.Value, flags uint64) { + fc := &fuzzerContext{fuzzer: f} + fc.doFuzz(v, flags) +} + +// fuzzerContext carries context about a single fuzzing run, which lets Fuzzer +// be thread-safe. +type fuzzerContext struct { + fuzzer *Fuzzer + curDepth int +} + +func (fc *fuzzerContext) doFuzz(v reflect.Value, flags uint64) { + if fc.curDepth >= fc.fuzzer.maxDepth { + return + } + fc.curDepth++ + defer func() { fc.curDepth-- }() + if !v.CanSet() { return } if flags&flagNoCustomFuzz == 0 { // Check for both pointer and non-pointer custom functions. - if v.CanAddr() && f.tryCustom(v.Addr()) { + if v.CanAddr() && fc.tryCustom(v.Addr()) { return } - if f.tryCustom(v) { + if fc.tryCustom(v) { return } } if fn, ok := fillFuncMap[v.Kind()]; ok { - fn(v, f.r) + fn(v, fc.fuzzer.r) return } switch v.Kind() { case reflect.Map: - if f.genShouldFill() { + if fc.fuzzer.genShouldFill() { v.Set(reflect.MakeMap(v.Type())) - n := f.genElementCount() + n := fc.fuzzer.genElementCount() for i := 0; i < n; i++ { key := reflect.New(v.Type().Key()).Elem() - f.doFuzz(key, 0) + fc.doFuzz(key, 0) val := reflect.New(v.Type().Elem()).Elem() - f.doFuzz(val, 0) + fc.doFuzz(val, 0) v.SetMapIndex(key, val) } return } v.Set(reflect.Zero(v.Type())) case reflect.Ptr: - if f.genShouldFill() { + if fc.fuzzer.genShouldFill() { v.Set(reflect.New(v.Type().Elem())) - f.doFuzz(v.Elem(), 0) + fc.doFuzz(v.Elem(), 0) return } v.Set(reflect.Zero(v.Type())) case reflect.Slice: - if f.genShouldFill() { - n := f.genElementCount() + if fc.fuzzer.genShouldFill() { + n := fc.fuzzer.genElementCount() v.Set(reflect.MakeSlice(v.Type(), n, n)) for i := 0; i < n; i++ { - f.doFuzz(v.Index(i), 0) + fc.doFuzz(v.Index(i), 0) } return } v.Set(reflect.Zero(v.Type())) case reflect.Array: - if f.genShouldFill() { + if fc.fuzzer.genShouldFill() { n := v.Len() for i := 0; i < n; i++ { - f.doFuzz(v.Index(i), 0) + fc.doFuzz(v.Index(i), 0) } return } v.Set(reflect.Zero(v.Type())) case reflect.Struct: for i := 0; i < v.NumField(); i++ { - f.doFuzz(v.Field(i), 0) + fc.doFuzz(v.Field(i), 0) } case reflect.Chan: fallthrough @@ -255,20 +289,20 @@ func (f *Fuzzer) doFuzz(v reflect.Value, flags uint64) { // tryCustom searches for custom handlers, and returns true iff it finds a match // and successfully randomizes v. -func (f *Fuzzer) tryCustom(v reflect.Value) bool { +func (fc *fuzzerContext) tryCustom(v reflect.Value) bool { // First: see if we have a fuzz function for it. - doCustom, ok := f.fuzzFuncs[v.Type()] + doCustom, ok := fc.fuzzer.fuzzFuncs[v.Type()] if !ok { // Second: see if it can fuzz itself. if v.CanInterface() { intf := v.Interface() if fuzzable, ok := intf.(Interface); ok { - fuzzable.Fuzz(Continue{f: f, Rand: f.r}) + fuzzable.Fuzz(Continue{fc: fc, Rand: fc.fuzzer.r}) return true } } // Finally: see if there is a default fuzz function. - doCustom, ok = f.defaultFuzzFuncs[v.Type()] + doCustom, ok = fc.fuzzer.defaultFuzzFuncs[v.Type()] if !ok { return false } @@ -294,8 +328,8 @@ func (f *Fuzzer) tryCustom(v reflect.Value) bool { } doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{ - f: f, - Rand: f.r, + fc: fc, + Rand: fc.fuzzer.r, })}) return true } @@ -310,7 +344,7 @@ type Interface interface { // Continue can be passed to custom fuzzing functions to allow them to use // the correct source of randomness and to continue fuzzing their members. type Continue struct { - f *Fuzzer + fc *fuzzerContext // For convenience, Continue implements rand.Rand via embedding. // Use this for generating any randomness if you want your fuzzing @@ -325,7 +359,7 @@ func (c Continue) Fuzz(obj interface{}) { panic("needed ptr!") } v = v.Elem() - c.f.doFuzz(v, 0) + c.fc.doFuzz(v, 0) } // FuzzNoCustom continues fuzzing obj, except that any custom fuzz function for @@ -338,7 +372,7 @@ func (c Continue) FuzzNoCustom(obj interface{}) { panic("needed ptr!") } v = v.Elem() - c.f.doFuzz(v, flagNoCustomFuzz) + c.fc.doFuzz(v, flagNoCustomFuzz) } // RandString makes a random string up to 20 characters long. The returned string diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE index d02f24fd5..6a66aea5e 100644 --- a/vendor/golang.org/x/oauth2/LICENSE +++ b/vendor/golang.org/x/oauth2/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The oauth2 Authors. All rights reserved. +Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md index b0ddf3c10..0f443e693 100644 --- a/vendor/golang.org/x/oauth2/README.md +++ b/vendor/golang.org/x/oauth2/README.md @@ -11,64 +11,25 @@ oauth2 package contains a client implementation for OAuth 2.0 spec. go get golang.org/x/oauth2 ~~~~ +Or you can manually git clone the repository to +`$(go env GOPATH)/src/golang.org/x/oauth2`. + See godoc for further documentation and examples. * [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) * [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) +## Policy for new packages -## App Engine +We no longer accept new provider-specific packages in this repo. For +defining provider endpoints and provider-specific OAuth2 behavior, we +encourage you to create packages elsewhere. We'll keep the existing +packages for compatibility. -In change 96e89be (March 2015) we removed the `oauth2.Context2` type in favor -of the [`context.Context`](https://golang.org/x/net/context#Context) type from -the `golang.org/x/net/context` package +## Report Issues / Send Patches -This means its no longer possible to use the "Classic App Engine" -`appengine.Context` type with the `oauth2` package. (You're using -Classic App Engine if you import the package `"appengine"`.) +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. -To work around this, you may use the new `"google.golang.org/appengine"` -package. This package has almost the same API as the `"appengine"` package, -but it can be fetched with `go get` and used on "Managed VMs" and well as -Classic App Engine. - -See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) -for information on updating your app. - -If you don't want to update your entire app to use the new App Engine packages, -you may use both sets of packages in parallel, using only the new packages -with the `oauth2` package. - - import ( - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - newappengine "google.golang.org/appengine" - newurlfetch "google.golang.org/appengine/urlfetch" - - "appengine" - ) - - func handler(w http.ResponseWriter, r *http.Request) { - var c appengine.Context = appengine.NewContext(r) - c.Infof("Logging a message with the old package") - - var ctx context.Context = newappengine.NewContext(r) - client := &http.Client{ - Transport: &oauth2.Transport{ - Source: google.AppEngineTokenSource(ctx, "scope"), - Base: &newurlfetch.Transport{Context: ctx}, - }, - } - client.Get("...") - } - -## Contributing - -We appreciate your help! - -To contribute, please read the contribution guidelines: - https://golang.org/doc/contribute.html - -Note that the Go project does not use GitHub pull requests but -uses Gerrit for code reviews. See the contribution guide for details. +The main issue tracker for the oauth2 repository is located at +https://github.com/golang/oauth2/issues. diff --git a/vendor/golang.org/x/oauth2/client_appengine.go b/vendor/golang.org/x/oauth2/client_appengine.go deleted file mode 100644 index 8962c49d1..000000000 --- a/vendor/golang.org/x/oauth2/client_appengine.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build appengine - -// App Engine hooks. - -package oauth2 - -import ( - "net/http" - - "golang.org/x/net/context" - "golang.org/x/oauth2/internal" - "google.golang.org/appengine/urlfetch" -) - -func init() { - internal.RegisterContextClientFunc(contextClientAppEngine) -} - -func contextClientAppEngine(ctx context.Context) (*http.Client, error) { - return urlfetch.Client(ctx), nil -} diff --git a/vendor/golang.org/x/oauth2/go.mod b/vendor/golang.org/x/oauth2/go.mod new file mode 100644 index 000000000..b34578155 --- /dev/null +++ b/vendor/golang.org/x/oauth2/go.mod @@ -0,0 +1,10 @@ +module golang.org/x/oauth2 + +go 1.11 + +require ( + cloud.google.com/go v0.34.0 + golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e + golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect + google.golang.org/appengine v1.4.0 +) diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go new file mode 100644 index 000000000..743487188 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/client_appengine.go @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build appengine + +package internal + +import "google.golang.org/appengine/urlfetch" + +func init() { + appengineClientHook = urlfetch.Client +} diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go new file mode 100644 index 000000000..03265e888 --- /dev/null +++ b/vendor/golang.org/x/oauth2/internal/doc.go @@ -0,0 +1,6 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package internal contains support packages for oauth2 package. +package internal diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go index e31541b39..c0ab196cf 100644 --- a/vendor/golang.org/x/oauth2/internal/oauth2.go +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go @@ -2,18 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( - "bufio" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "fmt" - "io" - "strings" ) // ParseKey converts the binary contents of a private key file @@ -30,7 +26,7 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { if err != nil { parsedKey, err = x509.ParsePKCS1PrivateKey(key) if err != nil { - return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err) + return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err) } } parsed, ok := parsedKey.(*rsa.PrivateKey) @@ -39,38 +35,3 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { } return parsed, nil } - -func ParseINI(ini io.Reader) (map[string]map[string]string, error) { - result := map[string]map[string]string{ - "": {}, // root section - } - scanner := bufio.NewScanner(ini) - currentSection := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, ";") { - // comment. - continue - } - if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { - currentSection = strings.TrimSpace(line[1 : len(line)-1]) - result[currentSection] = map[string]string{} - continue - } - parts := strings.SplitN(line, "=", 2) - if len(parts) == 2 && parts[0] != "" { - result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning ini: %v", err) - } - return result, nil -} - -func CondVal(v string) []string { - if v == "" { - return nil - } - return []string{v} -} diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go index 018b58ad1..355c38696 100644 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -2,25 +2,28 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( + "context" "encoding/json" + "errors" "fmt" "io" "io/ioutil" + "math" "mime" "net/http" "net/url" "strconv" "strings" + "sync" "time" - "golang.org/x/net/context" + "golang.org/x/net/context/ctxhttp" ) -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -60,22 +63,21 @@ type tokenJSON struct { TokenType string `json:"token_type"` RefreshToken string `json:"refresh_token"` ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number - Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in } func (e *tokenJSON) expiry() (t time.Time) { if v := e.ExpiresIn; v != 0 { return time.Now().Add(time.Duration(v) * time.Second) } - if v := e.Expires; v != 0 { - return time.Now().Add(time.Duration(v) * time.Second) - } return } type expirationTime int32 func (e *expirationTime) UnmarshalJSON(b []byte) error { + if len(b) == 0 || string(b) == "null" { + return nil + } var n json.Number err := json.Unmarshal(b, &n) if err != nil { @@ -85,92 +87,78 @@ func (e *expirationTime) UnmarshalJSON(b []byte) error { if err != nil { return err } + if i > math.MaxInt32 { + i = math.MaxInt32 + } *e = expirationTime(i) return nil } -var brokenAuthHeaderProviders = []string{ - "https://accounts.google.com/", - "https://api.codeswholesale.com/oauth/token", - "https://api.dropbox.com/", - "https://api.dropboxapi.com/", - "https://api.instagram.com/", - "https://api.netatmo.net/", - "https://api.odnoklassniki.ru/", - "https://api.pushbullet.com/", - "https://api.soundcloud.com/", - "https://api.twitch.tv/", - "https://app.box.com/", - "https://connect.stripe.com/", - "https://graph.facebook.com", // see https://github.com/golang/oauth2/issues/214 - "https://login.microsoftonline.com/", - "https://login.salesforce.com/", - "https://oauth.sandbox.trainingpeaks.com/", - "https://oauth.trainingpeaks.com/", - "https://oauth.vk.com/", - "https://openapi.baidu.com/", - "https://slack.com/", - "https://test-sandbox.auth.corp.google.com", - "https://test.salesforce.com/", - "https://user.gini.net/", - "https://www.douban.com/", - "https://www.googleapis.com/", - "https://www.linkedin.com/", - "https://www.strava.com/oauth/", - "https://www.wunderlist.com/oauth/", - "https://api.patreon.com/", - "https://sandbox.codeswholesale.com/oauth/token", +// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. +// +// Deprecated: this function no longer does anything. Caller code that +// wants to avoid potential extra HTTP requests made during +// auto-probing of the provider's auth style should set +// Endpoint.AuthStyle. +func RegisterBrokenAuthHeaderProvider(tokenURL string) {} + +// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. +type AuthStyle int + +const ( + AuthStyleUnknown AuthStyle = 0 + AuthStyleInParams AuthStyle = 1 + AuthStyleInHeader AuthStyle = 2 +) + +// authStyleCache is the set of tokenURLs we've successfully used via +// RetrieveToken and which style auth we ended up using. +// It's called a cache, but it doesn't (yet?) shrink. It's expected that +// the set of OAuth2 servers a program contacts over time is fixed and +// small. +var authStyleCache struct { + sync.Mutex + m map[string]AuthStyle // keyed by tokenURL } -// brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints. -var brokenAuthHeaderDomains = []string{ - ".force.com", - ".okta.com", - ".oktapreview.com", +// ResetAuthCache resets the global authentication style cache used +// for AuthStyleUnknown token requests. +func ResetAuthCache() { + authStyleCache.Lock() + defer authStyleCache.Unlock() + authStyleCache.m = nil } -func RegisterBrokenAuthHeaderProvider(tokenURL string) { - brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL) +// lookupAuthStyle reports which auth style we last used with tokenURL +// when calling RetrieveToken and whether we have ever done so. +func lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) { + authStyleCache.Lock() + defer authStyleCache.Unlock() + style, ok = authStyleCache.m[tokenURL] + return } -// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL -// implements the OAuth2 spec correctly -// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. -// In summary: -// - Reddit only accepts client secret in the Authorization header -// - Dropbox accepts either it in URL param or Auth header, but not both. -// - Google only accepts URL param (not spec compliant?), not Auth header -// - Stripe only accepts client secret in Auth header with Bearer method, not Basic -func providerAuthHeaderWorks(tokenURL string) bool { - for _, s := range brokenAuthHeaderProviders { - if strings.HasPrefix(tokenURL, s) { - // Some sites fail to implement the OAuth2 spec fully. - return false - } +// setAuthStyle adds an entry to authStyleCache, documented above. +func setAuthStyle(tokenURL string, v AuthStyle) { + authStyleCache.Lock() + defer authStyleCache.Unlock() + if authStyleCache.m == nil { + authStyleCache.m = make(map[string]AuthStyle) } - - if u, err := url.Parse(tokenURL); err == nil { - for _, s := range brokenAuthHeaderDomains { - if strings.HasSuffix(u.Host, s) { - return false - } - } - } - - // Assume the provider implements the spec properly - // otherwise. We can add more exceptions as they're - // discovered. We will _not_ be adding configurable hooks - // to this package to let users select server bugs. - return true + authStyleCache.m[tokenURL] = v } -func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) { - hc, err := ContextClient(ctx) - if err != nil { - return nil, err - } - bustedAuth := !providerAuthHeaderWorks(tokenURL) - if bustedAuth { +// newTokenRequest returns a new *http.Request to retrieve a new token +// from tokenURL using the provided clientID, clientSecret, and POST +// body parameters. +// +// inParams is whether the clientID & clientSecret should be encoded +// as the POST body. An 'inParams' value of true means to send it in +// the POST body (along with any values in v); false means to send it +// in the Authorization header. +func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { + if authStyle == AuthStyleInParams { + v = cloneURLValues(v) if clientID != "" { v.Set("client_id", clientID) } @@ -183,20 +171,78 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, return nil, err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if !bustedAuth { - req.SetBasicAuth(clientID, clientSecret) + if authStyle == AuthStyleInHeader { + req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) } - r, err := hc.Do(req) + return req, nil +} + +func cloneURLValues(v url.Values) url.Values { + v2 := make(url.Values, len(v)) + for k, vv := range v { + v2[k] = append([]string(nil), vv...) + } + return v2 +} + +func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) { + needsAuthStyleProbe := authStyle == 0 + if needsAuthStyleProbe { + if style, ok := lookupAuthStyle(tokenURL); ok { + authStyle = style + needsAuthStyleProbe = false + } else { + authStyle = AuthStyleInHeader // the first way we'll try + } + } + req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) + if err != nil { + return nil, err + } + token, err := doTokenRoundTrip(ctx, req) + if err != nil && needsAuthStyleProbe { + // If we get an error, assume the server wants the + // clientID & clientSecret in a different form. + // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. + // In summary: + // - Reddit only accepts client secret in the Authorization header + // - Dropbox accepts either it in URL param or Auth header, but not both. + // - Google only accepts URL param (not spec compliant?), not Auth header + // - Stripe only accepts client secret in Auth header with Bearer method, not Basic + // + // We used to maintain a big table in this code of all the sites and which way + // they went, but maintaining it didn't scale & got annoying. + // So just try both ways. + authStyle = AuthStyleInParams // the second way we'll try + req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) + token, err = doTokenRoundTrip(ctx, req) + } + if needsAuthStyleProbe && err == nil { + setAuthStyle(tokenURL, authStyle) + } + // Don't overwrite `RefreshToken` with an empty value + // if this was a token refreshing request. + if token != nil && token.RefreshToken == "" { + token.RefreshToken = v.Get("refresh_token") + } + return token, err +} + +func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { + r, err := ctxhttp.Do(ctx, ContextClient(ctx), req) if err != nil { return nil, err } - defer r.Body.Close() body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) + r.Body.Close() if err != nil { return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) } if code := r.StatusCode; code < 200 || code > 299 { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body) + return nil, &RetrieveError{ + Response: r, + Body: body, + } } var token *Token @@ -214,12 +260,6 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, Raw: vals, } e := vals.Get("expires_in") - if e == "" { - // TODO(jbd): Facebook's OAuth2 implementation is broken and - // returns expires_in field in expires. Remove the fallback to expires, - // when Facebook fixes their implementation. - e = vals.Get("expires") - } expires, _ := strconv.Atoi(e) if expires != 0 { token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) @@ -238,10 +278,17 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, } json.Unmarshal(body, &token.Raw) // no error checks for optional fields } - // Don't overwrite `RefreshToken` with an empty value - // if this was a token refreshing request. - if token.RefreshToken == "" { - token.RefreshToken = v.Get("refresh_token") + if token.AccessToken == "" { + return nil, errors.New("oauth2: server response missing access_token") } return token, nil } + +type RetrieveError struct { + Response *http.Response + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go index f1f173e34..572074a63 100644 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( + "context" "net/http" - - "golang.org/x/net/context" ) // HTTPClient is the context key to use with golang.org/x/net/context's @@ -20,50 +18,16 @@ var HTTPClient ContextKey // because nobody else can create a ContextKey, being unexported. type ContextKey struct{} -// ContextClientFunc is a func which tries to return an *http.Client -// given a Context value. If it returns an error, the search stops -// with that error. If it returns (nil, nil), the search continues -// down the list of registered funcs. -type ContextClientFunc func(context.Context) (*http.Client, error) +var appengineClientHook func(context.Context) *http.Client -var contextClientFuncs []ContextClientFunc - -func RegisterContextClientFunc(fn ContextClientFunc) { - contextClientFuncs = append(contextClientFuncs, fn) -} - -func ContextClient(ctx context.Context) (*http.Client, error) { +func ContextClient(ctx context.Context) *http.Client { if ctx != nil { if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return hc, nil + return hc } } - for _, fn := range contextClientFuncs { - c, err := fn(ctx) - if err != nil { - return nil, err - } - if c != nil { - return c, nil - } + if appengineClientHook != nil { + return appengineClientHook(ctx) } - return http.DefaultClient, nil -} - -func ContextTransport(ctx context.Context) http.RoundTripper { - hc, err := ContextClient(ctx) - // This is a rare error case (somebody using nil on App Engine). - if err != nil { - return ErrorTransport{err} - } - return hc.Transport -} - -// ErrorTransport returns the specified error on RoundTrip. -// This RoundTripper should be used in rare error cases where -// error handling can be postponed to response handling time. -type ErrorTransport struct{ Err error } - -func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) { - return nil, t.Err + return http.DefaultClient } diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 3e4835d7e..428283f0b 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -3,19 +3,20 @@ // license that can be found in the LICENSE file. // Package oauth2 provides support for making -// OAuth2 authorized and authenticated HTTP requests. +// OAuth2 authorized and authenticated HTTP requests, +// as specified in RFC 6749. // It can additionally grant authorization with Bearer JWT. package oauth2 // import "golang.org/x/oauth2" import ( "bytes" + "context" "errors" "net/http" "net/url" "strings" "sync" - "golang.org/x/net/context" "golang.org/x/oauth2/internal" ) @@ -25,17 +26,13 @@ import ( // Deprecated: Use context.Background() or context.TODO() instead. var NoContext = context.TODO() -// RegisterBrokenAuthHeaderProvider registers an OAuth2 server -// identified by the tokenURL prefix as an OAuth2 implementation -// which doesn't support the HTTP Basic authentication -// scheme to authenticate with the authorization server. -// Once a server is registered, credentials (client_id and client_secret) -// will be passed as query parameters rather than being present -// in the Authorization header. -// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. -func RegisterBrokenAuthHeaderProvider(tokenURL string) { - internal.RegisterBrokenAuthHeaderProvider(tokenURL) -} +// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. +// +// Deprecated: this function no longer does anything. Caller code that +// wants to avoid potential extra HTTP requests made during +// auto-probing of the provider's auth style should set +// Endpoint.AuthStyle. +func RegisterBrokenAuthHeaderProvider(tokenURL string) {} // Config describes a typical 3-legged OAuth2 flow, with both the // client application information and the server's endpoint URLs. @@ -70,13 +67,38 @@ type TokenSource interface { Token() (*Token, error) } -// Endpoint contains the OAuth 2.0 provider's authorization and token +// Endpoint represents an OAuth 2.0 provider's authorization and token // endpoint URLs. type Endpoint struct { AuthURL string TokenURL string + + // AuthStyle optionally specifies how the endpoint wants the + // client ID & client secret sent. The zero value means to + // auto-detect. + AuthStyle AuthStyle } +// AuthStyle represents how requests for tokens are authenticated +// to the server. +type AuthStyle int + +const ( + // AuthStyleAutoDetect means to auto-detect which authentication + // style the provider wants by trying both ways and caching + // the successful way for the future. + AuthStyleAutoDetect AuthStyle = 0 + + // AuthStyleInParams sends the "client_id" and "client_secret" + // in the POST body as application/x-www-form-urlencoded parameters. + AuthStyleInParams AuthStyle = 1 + + // AuthStyleInHeader sends the client_id and client_password + // using HTTP Basic Authorization. This is an optional style + // described in the OAuth2 RFC 6749 section 2.3.1. + AuthStyleInHeader AuthStyle = 2 +) + var ( // AccessTypeOnline and AccessTypeOffline are options passed // to the Options.AuthCodeURL method. They modify the @@ -117,21 +139,30 @@ func SetAuthURLParam(key, value string) AuthCodeOption { // that asks for permissions for the required scopes explicitly. // // State is a token to protect the user from CSRF attacks. You must -// always provide a non-zero string and validate that it matches the +// always provide a non-empty string and validate that it matches the // the state query parameter on your redirect callback. // See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. // // Opts may include AccessTypeOnline or AccessTypeOffline, as well // as ApprovalForce. +// It can also be used to pass the PKCE challenge. +// See https://www.oauth.com/oauth2-servers/pkce/ for more info. func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { var buf bytes.Buffer buf.WriteString(c.Endpoint.AuthURL) v := url.Values{ "response_type": {"code"}, "client_id": {c.ClientID}, - "redirect_uri": internal.CondVal(c.RedirectURL), - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - "state": internal.CondVal(state), + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + if state != "" { + // TODO(light): Docs say never to omit state; don't allow empty. + v.Set("state", state) } for _, opt := range opts { opt.setValue(v) @@ -154,15 +185,17 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { // and when other authorization grant types are not available." // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. // -// The HTTP client to use is derived from the context. -// If nil, http.DefaultClient is used. +// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ + v := url.Values{ "grant_type": {"password"}, "username": {username}, "password": {password}, - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - }) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + return retrieveToken(ctx, c, v) } // Exchange converts an authorization code into a token. @@ -170,17 +203,25 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor // It is used after a resource provider redirects the user back // to the Redirect URI (the URL obtained from AuthCodeURL). // -// The HTTP client to use is derived from the context. -// If a client is not provided via the context, http.DefaultClient is used. +// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. // // The code will be in the *http.Request.FormValue("code"). Before // calling Exchange, be sure to validate FormValue("state"). -func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ - "grant_type": {"authorization_code"}, - "code": {code}, - "redirect_uri": internal.CondVal(c.RedirectURL), - }) +// +// Opts may include the PKCE verifier code if previously used in AuthCodeURL. +// See https://www.oauth.com/oauth2-servers/pkce/ for more info. +func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { + v := url.Values{ + "grant_type": {"authorization_code"}, + "code": {code}, + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + for _, opt := range opts { + opt.setValue(v) + } + return retrieveToken(ctx, c, v) } // Client returns an HTTP client using the provided token. @@ -291,20 +332,20 @@ var HTTPClient internal.ContextKey // NewClient creates an *http.Client from a Context and TokenSource. // The returned client is not valid beyond the lifetime of the context. // +// Note that if a custom *http.Client is provided via the Context it +// is used only for token acquisition and is not used to configure the +// *http.Client returned from NewClient. +// // As a special case, if src is nil, a non-OAuth2 client is returned // using the provided context. This exists to support related OAuth2 // packages. func NewClient(ctx context.Context, src TokenSource) *http.Client { if src == nil { - c, err := internal.ContextClient(ctx) - if err != nil { - return &http.Client{Transport: internal.ErrorTransport{Err: err}} - } - return c + return internal.ContextClient(ctx) } return &http.Client{ Transport: &Transport{ - Base: internal.ContextTransport(ctx), + Base: internal.ContextClient(ctx).Transport, Source: ReuseTokenSource(nil, src), }, } diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 7a3167f15..822720341 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -5,13 +5,14 @@ package oauth2 import ( + "context" + "fmt" "net/http" "net/url" "strconv" "strings" "time" - "golang.org/x/net/context" "golang.org/x/oauth2/internal" ) @@ -20,7 +21,7 @@ import ( // expirations due to client-server time mismatches. const expiryDelta = 10 * time.Second -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -117,13 +118,16 @@ func (t *Token) Extra(key string) interface{} { return v } +// timeNow is time.Now but pulled out as a variable for tests. +var timeNow = time.Now + // expired reports whether the token is expired. // t must be non-nil. func (t *Token) expired() bool { if t.Expiry.IsZero() { return false } - return t.Expiry.Add(-expiryDelta).Before(time.Now()) + return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow()) } // Valid reports whether t is non-nil, has an AccessToken, and is not expired. @@ -150,9 +154,25 @@ func tokenFromInternal(t *internal.Token) *Token { // This token is then mapped from *internal.Token into an *oauth2.Token which is returned along // with an error.. func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v) + tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle)) if err != nil { + if rErr, ok := err.(*internal.RetrieveError); ok { + return nil, (*RetrieveError)(rErr) + } return nil, err } return tokenFromInternal(tk), nil } + +// RetrieveError is the error returned when the token endpoint returns a +// non-2XX HTTP status code. +type RetrieveError struct { + Response *http.Response + // Body is the body that was consumed by reading Response.Body. + // It may be truncated. + Body []byte +} + +func (r *RetrieveError) Error() string { + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go index 92ac7e253..aa0d34f1e 100644 --- a/vendor/golang.org/x/oauth2/transport.go +++ b/vendor/golang.org/x/oauth2/transport.go @@ -31,9 +31,17 @@ type Transport struct { } // RoundTrip authorizes and authenticates the request with an -// access token. If no token exists or token is expired, -// tries to refresh/fetch a new token. +// access token from Transport's Source. func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + reqBodyClosed := false + if req.Body != nil { + defer func() { + if !reqBodyClosed { + req.Body.Close() + } + }() + } + if t.Source == nil { return nil, errors.New("oauth2: Transport's Source is nil") } @@ -46,6 +54,10 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { token.SetAuthHeader(req2) t.setModReq(req, req2) res, err := t.base().RoundTrip(req2) + + // req.Body is assumed to have been closed by the base RoundTripper. + reqBodyClosed = true + if err != nil { t.setModReq(req, nil) return nil, err