diff options
71 files changed, 1331 insertions, 625 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 655fa3830..5c4cf470c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -143,6 +143,27 @@ gating_task: on_failure: failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh' +# This task checks to make sure that we can still build an rpm from the +# source code using contrib/rpm/podman.spec.in +rpmbuild_task: + + only_if: $CIRRUS_BRANCH != $DEST_BRANCH + depends_on: + - "gating" + env: + CIRRUS_WORKING_DIR: "/usr/src/libpod" + + container: + image: quay.io/libpod/rpmbuild:$DEST_BRANCH + cpu: 2 + memory: 4 + + rpmbuild_script: + - 'make -C ${CIRRUS_WORKING_DIR} -f ${CIRRUS_WORKING_DIR}/.copr/Makefile' + - 'rpmbuild --rebuild ${CIRRUS_WORKING_DIR}/podman-*.src.rpm' + + on_failure: + failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh |& ${TIMESTAMP}' # This task runs `make vendor` followed by ./hack/tree_status.sh to check # whether the git tree is clean. The reasoning for that is to make sure @@ -316,8 +337,10 @@ meta_task: # Remove old and disused images based on labels set by meta_task image_prune_task: - # Do not run this frequently - only_if: $CIRRUS_BRANCH == $DEST_BRANCH + # This should ONLY ever run from the master branch, and never + # anywhere else so it's behavior is always consistent, even + # as new branches are created. + only_if: $CIRRUS_BRANCH == "master" depends_on: - "meta" @@ -710,6 +733,7 @@ success_task: - "meta" - "image_prune" - "testing" + - "rpmbuild" - "special_testing_rootless" - "special_testing_in_podman" - "special_testing_cgroupv2" diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md new file mode 100644 index 000000000..850e68db0 --- /dev/null +++ b/CODE-OF-CONDUCT.md @@ -0,0 +1,3 @@ +## The Libpod Project Community Code of Conduct + +The Libpod project which includes Podman, follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md). @@ -582,7 +582,7 @@ install.libseccomp.sudo: cmd/podman/varlink/iopodman.go: .gopathok cmd/podman/varlink/io.podman.varlink -ifeq ("$(shell uname -o)", "GNU/Linux") +ifneq (,$(findstring Linux,$(shell uname -s))) # Only generate the varlink code on Linux (see issue #4814). GO111MODULE=off $(GO) generate ./cmd/podman/varlink/... endif diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index 604e8d31c..b4d249c66 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -6,7 +6,6 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/adapter" - "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -65,17 +64,6 @@ func commitCmd(c *cliconfig.CommitValues) error { if len(args) > 1 { reference = args[1] } - if c.Flag("change").Changed { - for _, change := range c.Change { - splitChange := strings.Split(strings.ToUpper(change), "=") - if len(splitChange) == 1 { - splitChange = strings.Split(strings.ToUpper(change), " ") - } - if !util.StringInSlice(splitChange[0], ChangeCmds) { - return errors.Errorf("invalid syntax for --change: %s", change) - } - } - } iid, err := runtime.Commit(getContext(), c, container, reference) if err != nil { diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 7610edbc0..6fa2b3c71 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -257,6 +257,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Add a host device to the container (default [])", ) createFlags.StringSlice( + "device-cgroup-rule", []string{}, + "Add a rule to the cgroup allowed devices list", + ) + createFlags.StringSlice( "device-read-bps", []string{}, "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)", ) diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 1cbb3f45e..f800d68fe 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -4,7 +4,6 @@ import ( "fmt" "io" "os" - "strings" buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/image/v5/docker" @@ -15,6 +14,7 @@ import ( "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/util" + "github.com/docker/distribution/reference" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -101,18 +101,32 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { } } - arr := strings.SplitN(args[0], ":", 2) - if len(arr) == 2 { - if c.Bool("all-tags") { - return errors.Errorf("tag can't be used with --all-tags") + ctx := getContext() + imageName := args[0] + + imageRef, err := alltransports.ParseImageName(imageName) + if err != nil { + imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), imageName)) + if err != nil { + return errors.Errorf("invalid image reference %q", imageName) } } - ctx := getContext() - imgArg := args[0] + var writer io.Writer + if !c.Quiet { + writer = os.Stderr + } + // Special-case for docker-archive which allows multiple tags. + if imageRef.Transport().Name() == dockerarchive.Transport.Name() { + newImage, err := runtime.LoadFromArchiveReference(getContext(), imageRef, c.SignaturePolicy, writer) + if err != nil { + return errors.Wrapf(err, "error pulling image %q", imageName) + } + fmt.Println(newImage[0].ID()) + return nil + } var registryCreds *types.DockerAuthConfig - if c.Flag("creds").Changed { creds, err := util.ParseRegistryCreds(c.Creds) if err != nil { @@ -120,14 +134,6 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { } registryCreds = creds } - - var ( - writer io.Writer - ) - if !c.Quiet { - writer = os.Stderr - } - dockerRegistryOptions := image.DockerRegistryOptions{ DockerRegistryCreds: registryCreds, DockerCertPath: c.CertDir, @@ -138,79 +144,52 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify) } - // Special-case for docker-archive which allows multiple tags. - if strings.HasPrefix(imgArg, dockerarchive.Transport.Name()+":") { - srcRef, err := alltransports.ParseImageName(imgArg) - if err != nil { - return errors.Wrapf(err, "error parsing %q", imgArg) - } - newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer) - if err != nil { - return errors.Wrapf(err, "error pulling image from %q", imgArg) - } - fmt.Println(newImage[0].ID()) - - return nil - } - - // FIXME: the default pull consults the registries.conf's search registries - // while the all-tags pull does not. This behavior must be fixed in the - // future and span across c/buildah, c/image and c/libpod to avoid redundant - // and error prone code. - // - // See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background - // information. if !c.Bool("all-tags") { - newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) + newImage, err := runtime.New(getContext(), imageName, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) if err != nil { - return errors.Wrapf(err, "error pulling image %q", imgArg) + return errors.Wrapf(err, "error pulling image %q", imageName) } fmt.Println(newImage.ID()) return nil } - // FIXME: all-tags should use the libpod backend instead of baking its own bread. - spec := imgArg - systemContext := image.GetSystemContext("", c.Authfile, false) - srcRef, err := alltransports.ParseImageName(spec) + // --all-tags requires the docker transport + if imageRef.Transport().Name() != docker.Transport.Name() { + return errors.New("--all-tags requires docker transport") + } + + // all-tags doesn't work with a tagged reference, so let's check early + namedRef, err := reference.Parse(imageName) if err != nil { - dockerTransport := "docker://" - logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, dockerTransport, err) - spec = dockerTransport + spec - srcRef2, err2 := alltransports.ParseImageName(spec) - if err2 != nil { - return errors.Wrapf(err2, "error parsing image name %q", imgArg) - } - srcRef = srcRef2 + return errors.Wrapf(err, "error parsing %q", imageName) } - var names []string - if srcRef.DockerReference() == nil { - return errors.New("Non-docker transport is currently not supported") + if _, isTagged := namedRef.(reference.Tagged); isTagged { + return errors.New("--all-tags requires a reference without a tag") + } - tags, err := docker.GetRepositoryTags(ctx, systemContext, srcRef) + + systemContext := image.GetSystemContext("", c.Authfile, false) + tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef) if err != nil { return errors.Wrapf(err, "error getting repository tags") } - for _, tag := range tags { - name := spec + ":" + tag - names = append(names, name) - } var foundIDs []string - foundImage := true - for _, name := range names { + for _, tag := range tags { + name := imageName + ":" + tag newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) if err != nil { logrus.Errorf("error pulling image %q", name) - foundImage = false continue } foundIDs = append(foundIDs, newImage.ID()) } - if len(names) == 1 && !foundImage { - return errors.Wrapf(err, "error pulling image %q", imgArg) + + if len(tags) != len(foundIDs) { + return errors.Errorf("error pulling image %q", imageName) } - if len(names) > 1 { + + if len(foundIDs) > 1 { fmt.Println("Pulled Images:") } for _, id := range foundIDs { diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index 9459247ed..ff3846e70 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -640,6 +640,11 @@ func GetNamespaces(pid int) *Namespace { } } +// GetNamespaceInfo is an exported wrapper for getNamespaceInfo +func GetNamespaceInfo(path string) (string, error) { + return getNamespaceInfo(path) +} + func getNamespaceInfo(path string) (string, error) { val, err := os.Readlink(path) if err != nil { diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 010c80373..be5adcccb 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -22,6 +22,7 @@ import ( "github.com/containers/libpod/pkg/inspect" ns "github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/seccomp" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" "github.com/docker/go-connections/nat" @@ -31,10 +32,6 @@ import ( "github.com/sirupsen/logrus" ) -// seccompLabelKey is the key of the image annotation embedding a seccomp -// profile. -const seccompLabelKey = "io.containers.seccomp.profile" - func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) { var ( healthCheck *manifest.Schema2HealthConfig @@ -109,11 +106,11 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } if overrideOS == "" && imageData.Os != goruntime.GOOS { - return nil, nil, errors.Errorf("incompatible image OS %q on %q host", imageData.Os, goruntime.GOOS) + logrus.Infof("Using %q (OS) image on %q host", imageData.Os, goruntime.GOOS) } if overrideArch == "" && imageData.Architecture != goruntime.GOARCH { - return nil, nil, errors.Errorf("incompatible image architecture %q on %q host", imageData.Architecture, goruntime.GOARCH) + logrus.Infof("Using %q (architecture) on %q host", imageData.Architecture, goruntime.GOARCH) } names := newImage.Names() @@ -713,11 +710,11 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. // SECCOMP if data != nil { - if value, exists := labels[seccompLabelKey]; exists { + if value, exists := labels[seccomp.ContainerImageLabel]; exists { secConfig.SeccompProfileFromImage = value } } - if policy, err := cc.LookupSeccompPolicy(c.String("seccomp-policy")); err != nil { + if policy, err := seccomp.LookupPolicy(c.String("seccomp-policy")); err != nil { return nil, err } else { secConfig.SeccompPolicy = policy @@ -761,6 +758,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. CPURtPeriod: c.Uint64("cpu-rt-period"), CPURtRuntime: c.Int64("cpu-rt-runtime"), CPUs: c.Float64("cpus"), + DeviceCgroupRules: c.StringSlice("device-cgroup-rule"), DeviceReadBps: c.StringSlice("device-read-bps"), DeviceReadIOps: c.StringSlice("device-read-iops"), DeviceWriteBps: c.StringSlice("device-write-bps"), diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go index cfb3f612c..ee212234f 100644 --- a/cmd/podman/shared/intermediate.go +++ b/cmd/podman/shared/intermediate.go @@ -386,6 +386,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["detach"] = newCRBool(c, "detach") m["detach-keys"] = newCRString(c, "detach-keys") m["device"] = newCRStringSlice(c, "device") + m["device-cgroup-rule"] = newCRStringSlice(c, "device-cgroup-rule") m["device-read-bps"] = newCRStringSlice(c, "device-read-bps") m["device-read-iops"] = newCRStringSlice(c, "device-read-iops") m["device-write-bps"] = newCRStringSlice(c, "device-write-bps") diff --git a/code-of-conduct.md b/code-of-conduct.md deleted file mode 100644 index 215ce7ac6..000000000 --- a/code-of-conduct.md +++ /dev/null @@ -1,55 +0,0 @@ -## Kubernetes Community Code of Conduct - -### Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of fostering -an open and welcoming community, we pledge to respect all people who contribute -through reporting issues, posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for -everyone, regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, body size, race, ethnicity, age, -religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery. -* Personal attacks. -* Trolling or insulting/derogatory comments. -* Public or private harassment. -* Publishing other's private information, such as physical or electronic addresses, - without explicit permission. -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are not -aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers -commit themselves to fairly and consistently applying these principles to every aspect -of managing this project. Project maintainers who do not follow or enforce the Code of -Conduct may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a Kubernetes maintainer, Sarah Novotny <sarahnovotny@google.com>, and/or Dan Kohn <dan@linuxfoundation.org>. - -This Code of Conduct is adapted from the Contributor Covenant -(http://contributor-covenant.org), version 1.2.0, available at -http://contributor-covenant.org/version/1/2/0/ - -### Kubernetes Events Code of Conduct - -Kubernetes events are working conferences intended for professional networking and collaboration in the -Kubernetes community. Attendees are expected to behave according to professional standards and in accordance -with their employer's policies on appropriate workplace behavior. - -While at Kubernetes events or related social networking opportunities, attendees should not engage in -discriminatory or offensive speech or actions regarding gender, sexuality, race, or religion. Speakers should -be especially aware of these concerns. - -The Kubernetes team does not condone any statements by speakers contrary to these standards. The Kubernetes -team reserves the right to deny entrance and/or eject from an event (without refund) any individual found to -be engaging in discriminatory or offensive speech or actions. - -Please bring any concerns to the immediate attention of the Kubernetes event staff. diff --git a/completions/bash/podman b/completions/bash/podman index 56559c142..d1dcef0a4 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1221,8 +1221,11 @@ _podman_system() { subcommands=" df info + migrate prune + renumber reset + service " __podman_subcommands "$subcommands" && return @@ -1311,7 +1314,6 @@ _podman_build() { --net --network --pid - --runtime --runtime-flag --security-opt --shm-size @@ -1329,15 +1331,10 @@ _podman_build() { -v " - local all_options="$options_with_args $boolean_options" - - case "$prev" in - --runtime) - COMPREPLY=($(compgen -W 'runc runv' -- "$cur")) + case "$prev" in + --file|-f) + COMPREPLY=($(compgen -W "`ls`" -- "$cur")) ;; - $(__podman_to_extglob "$options_with_args")) - return - ;; esac case "$cur" in @@ -1876,6 +1873,7 @@ _podman_container_run() { --cpuset-mems --cpu-shares -c --device + --device-cgroup-rule --device-read-bps --device-read-iops --device-write-bps diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 4e4dc5d21..276dd327e 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -385,6 +385,7 @@ mkdir -p src/%{provider}.%{provider_tld}/%{project} ln -s ../../../../ src/%{import_path} popd ln -s vendor src +export GO111MODULE=off export GOPATH=$(pwd)/_build:$(pwd):$(pwd):%{gopath} export BUILDTAGS="varlink selinux seccomp $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh) $(%{hackdir}/hack/libdm_tag.sh) exclude_graphdriver_devicemapper" @@ -507,7 +508,7 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %files %license LICENSE -%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md +%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md %{_bindir}/%{name} %{_datadir}/bash-completion/completions/* %{_datadir}/zsh/site-functions/* @@ -523,19 +524,19 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %if 0%{?with_devel} %files -n libpod-devel -f devel.file-list %license LICENSE -%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md +%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md %dir %{gopath}/src/%{provider}.%{provider_tld}/%{project} %endif %if 0%{?with_unit_test} && 0%{?with_devel} %files unit-test-devel -f unit-test-devel.file-list %license LICENSE -%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md +%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md %endif %files -n podman-remote %license LICENSE -%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md +%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md %{_bindir}/%{name}-remote %if %{with doc} diff --git a/contrib/spec/python-podman.spec.in b/contrib/spec/python-podman.spec.in index 6296586dd..b921f2645 100644 --- a/contrib/spec/python-podman.spec.in +++ b/contrib/spec/python-podman.spec.in @@ -92,7 +92,7 @@ popd %files %license LICENSE -%doc README.md CONTRIBUTING.md install.md code-of-conduct.md transfer.md +%doc README.md CONTRIBUTING.md install.md CODE-OF-CONDUCT.md transfer.md %{_bindir}/pypodman %{_mandir}/man1/pypodman.1* %dir %{python3_sitelib}/podman diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 977382e61..ca38be6a1 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -209,6 +209,13 @@ Note: if the user only has access rights via a group then accessing the device from inside a rootless container will fail. The `crun` runtime offers a workaround for this by adding the option `--annotation run.oci.keep_original_groups=1`. +**--device-cgroup-rule**="type major:minor mode" + +Add a rule to the cgroup allowed devices list. The rule is expected to be in the format specified in the Linux kernel documentation (Documentation/cgroup-v1/devices.txt): + - type: a (all), c (char), or b (block); + - major and minor: either a number, or * for all; + - mode: a composition of r (read), w (write), and m (mknod(2)). + **--device-read-bps**=*path* Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb) diff --git a/docs/source/markdown/podman-system-service.1.md b/docs/source/markdown/podman-system-service.1.md index a71ce9dc0..a2fefe4dd 100644 --- a/docs/source/markdown/podman-system-service.1.md +++ b/docs/source/markdown/podman-system-service.1.md @@ -32,12 +32,12 @@ Print usage statement. Run an API listening for 5 seconds using the default socket. ``` -podman service --timeout 5000 +podman system service --timeout 5000 ``` Run the podman varlink service with an alternate URI and accept the default timeout. ``` -$ podman service --varlink unix:/tmp/io.podman +$ podman system service --varlink unix:/tmp/io.podman ``` ## SEE ALSO @@ -38,7 +38,7 @@ require ( github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 // indirect - github.com/gorilla/mux v1.7.3 + github.com/gorilla/mux v1.7.4 github.com/gorilla/schema v1.1.0 github.com/hashicorp/go-multierror v1.0.0 github.com/hpcloud/tail v1.0.0 @@ -78,7 +78,7 @@ require ( google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 // indirect gopkg.in/yaml.v2 v2.2.8 k8s.io/api v0.17.2 - k8s.io/apimachinery v0.17.2 + k8s.io/apimachinery v0.17.3 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a // indirect ) @@ -1,6 +1,5 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg= github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -8,18 +7,13 @@ github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.0 h1:vhoV+DUHnRZdKW1i5UMjAk2G4JY8wN4ayRfYDNdEhwo= github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c h1:YMP6olTU903X3gxQJckdmiP8/zkSMq4kN3uipsU9XjU= github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8= github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -37,12 +31,10 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -68,30 +60,17 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784 h1:rqUVLD8I859xRgUx/WMC3v7QAFqbLKZbs+0kqYboRJc= github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w= -github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc= github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7/Eu+jpahihy8= github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o= -github.com/containers/buildah v1.12.0 h1:bi/8ACl8qobazwfYgNze5y+aRuBIG+R7lMStFbnDOxE= -github.com/containers/buildah v1.12.0/go.mod h1:yzPuQ/mJTPsfSLCyBPbeaoXgBLanjnf36M2cDzyckMg= github.com/containers/buildah v1.13.1 h1:EdhllQxXmOZ56mGFf68AkrpIj9XtEkkGq0WaPWFuGM0= github.com/containers/buildah v1.13.1/go.mod h1:U0LcOzSqoYdyQC5L2hMeLbtCDuCCLxmZV1eb+SWY4GA= -github.com/containers/common v0.0.3 h1:C2Zshb0w720FqPa42MCRuiGfbW0kwbURRwvK1EWIC5I= -github.com/containers/common v0.0.3/go.mod h1:CaOgMRiwi2JJHISMZ6VPPZhQYFUDRv3YYVss2RqUCMg= github.com/containers/common v0.0.7 h1:eKYZLKfJ2d/RNDgecLDFv45cHb4imYzIcrQHx1Y029M= github.com/containers/common v0.0.7/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI= -github.com/containers/conmon v2.0.9+incompatible h1:YcEgk0Ny1WBdH35M2LKe2cG6FiQqzDdVaURw84XvS7A= -github.com/containers/conmon v2.0.9+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.10+incompatible h1:EiwL41r5vx8SxG+dyUmbJ3baV9GUWjijPOdCkzM6gWU= github.com/containers/conmon v2.0.10+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= -github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4= -github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY= -github.com/containers/image/v5 v5.1.0 h1:5FjAvPJniamuNNIQHkh4PnsL+n+xzs6Aonzaz5dqTEo= github.com/containers/image/v5 v5.1.0/go.mod h1:BKlMD34WxRo1ruGHHEOrPQP0Qci7SWoPwU6fS7arsCU= github.com/containers/image/v5 v5.2.0 h1:DowY5OII5x9Pb6Pt76vnHU79BgG4/jdwhZjeAj2R+t8= github.com/containers/image/v5 v5.2.0/go.mod h1:IAub4gDGvXoxaIAdNy4e3FbVTDPVNMv9F0UfVVFbYCU= @@ -103,28 +82,16 @@ github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJ github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/psgo v1.4.0 h1:D8B4fZCCZhYgc8hDyMPCiShOinmOB1TP1qe46sSC19k= github.com/containers/psgo v1.4.0/go.mod h1:ENXXLQ5E1At4K0EUsGogXBJi/C28gwqkONWeLPI9fJ8= -github.com/containers/storage v1.13.2/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA= -github.com/containers/storage v1.13.4 h1:j0bBaJDKbUHtAW1MXPFnwXJtqcH+foWeuXK1YaBV5GA= -github.com/containers/storage v1.13.4/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA= github.com/containers/storage v1.13.5/go.mod h1:HELz8Sn+UVbPaUZMI8RvIG9doD4y4z6Gtg4k7xdd2ZY= -github.com/containers/storage v1.15.3 h1:+lFSQZnnKUFyUEtguIgdoQLJfWSuYz+j/wg5GxLtsN4= github.com/containers/storage v1.15.3/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8= -github.com/containers/storage v1.15.4 h1:eiUtV9MOTnPHibO18nDRI+aDhKudY7WmAiJdyVMsqSM= -github.com/containers/storage v1.15.4/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8= -github.com/containers/storage v1.15.5 h1:dBZx9yRFHod9c8FVaXlVtRqr2cmlAhpl+9rt87cE7J4= github.com/containers/storage v1.15.5/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8= -github.com/containers/storage v1.15.7 h1:ecPmv2y/qpxeSTHZ147jQLO6to8wDn8yUPtDCZlz0H4= -github.com/containers/storage v1.15.7/go.mod h1:gLZIp+/hP8nFn9tLS0uJlnk4h1tSoDu3oS2eFiaIqkE= github.com/containers/storage v1.15.8 h1:ef7OfUMTpyq0PIVAhV7qfufEI92gAldk25nItrip+6Q= github.com/containers/storage v1.15.8/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg= -github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= @@ -146,19 +113,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65 h1:4zlOyrJUbYnrvlzChJ+jP2J3i77Jbhm336NEuCv7kZo= github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.0.0-20180522102801-da99009bbb11/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 h1:oqgGT9O61YAYvI41EBsLePOr+LE6roB0xY4gpkZuFSE= github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f h1:Sm8iD2lifO31DwXfkGzq8VgA7rwxPjRsYmeo0K/dF9Y= github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/docker-credential-helpers v0.6.1 h1:Dq4iIfcM7cNtddhLVWe9h4QDjsi4OER3Z8voPu/I52g= -github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.0.0-20180212134524-7beb39f0b969/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= @@ -170,17 +132,13 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 h1:moehPjPiGUaWdwgOl92xRyFHJyaqXDHcCyW9M6nmCK4= github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= -github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs= github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/elazarl/goproxy/ext v0.0.0-20190911111923-ecfe977594f1 h1:8B7WF1rIoM8H1smfpXFvOawSAzlRDMVzoGu9zE3+OCk= github.com/elazarl/goproxy/ext v0.0.0-20190911111923-ecfe977594f1/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -188,7 +146,6 @@ github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -200,7 +157,6 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-ini/ini v1.51.1 h1:/QG3cj23k5V8mOl4JnNzUNhc1kr/jzMiNsNuWKcx8gM= github.com/go-ini/ini v1.51.1/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -225,29 +181,23 @@ github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gogo/protobuf v0.0.0-20170815085658-fcdc5011193f/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -256,16 +206,15 @@ github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIE github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v0.0.0-20170217192616-94e7d24fd285/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= @@ -283,8 +232,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -296,11 +243,8 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -311,17 +255,11 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.7.2 h1:liMOoeIvFpr9kEvalrZ7VVBA4wGf7zfOgwBjzz/5g2Y= github.com/klauspost/compress v1.7.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.8.1 h1:oygt2ychZFHOB6M9gUgajzgKrwRgHbGC77NwA4COVgI= github.com/klauspost/compress v1.8.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.4 h1:xhvAeUPQ2drNUhKtrGdTGNvV9nNafHMUkRyLkzxJoB4= github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA= github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM= github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -329,28 +267,20 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9wIsXc= github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWePHKOs= -github.com/mattn/go-shellwords v1.0.7/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.9 h1:eaB5JspOwiKKcHdqcjbfe5lA9cNn/4NRRtddXJCimqk= github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -370,57 +300,44 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd h1:3k5dpxjeXlUuz8STW9BE2WsvPnaMcmlfGKAbe3J5v+0= github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd/go.mod h1:YBPKCT1PrhoFU743gPdtJNp+LmM0QlGMWME1J+FJtQI= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= -github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c h1:xa+eQWKuJ9MbB9FBL/eoNvDFvveAkz2LQoz8PzX7Q/4= github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c/go.mod h1:GhAqVMEWnTcW2dxoD/SO3n2enrgWl3y6Dnx4m59GvcA= -github.com/mtrmac/gpgme v0.1.1 h1:a5ISnvahzTzBH0m/klhehN68N+9+/jLwhpPFtH3oPAQ= github.com/mtrmac/gpgme v0.1.1/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI= github.com/mtrmac/gpgme v0.1.2 h1:dNOmvYmsrakgW7LcgiprD0yfRuQQe8/C8F6Z+zogO3s= github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 h1:yN8BPXVwMBAm3Cuvh1L5XE8XpvYRMdsVLd82ILprhUU= github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8 h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0= github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190827142921-dd075602f158/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc= @@ -431,16 +348,12 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.m github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU= github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4FtGEe8bFg= github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= -github.com/opencontainers/selinux v1.3.0 h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqGe5TgR0g= github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/opencontainers/selinux v1.3.1 h1:dn2Rc3wTEvTB6iVqoFrKKeMb0uZ38ZheeyMu2h5C1TI= github.com/opencontainers/selinux v1.3.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 h1:enQG2QUGwug4fR1yM6hL0Fjzx6Km/exZY6RbSPwMu3o= github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316/go.mod h1:dv+J0b/HWai0QnMVb37/H0v36klkLBi2TNpPeWDxX10= -github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible h1:s55wx8JIG/CKnewev892HifTBrtKzMdvgB3rm4rxC2s= -github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= github.com/openshift/imagebuilder v1.1.1 h1:KAUR31p8UBJdfVO42azWgb+LeMAed2zaKQ19e0C0X2I= github.com/openshift/imagebuilder v1.1.1/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= @@ -451,23 +364,18 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k= github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7 h1:gGBSHPOU7g8YjTbhwn+lvFm2VDEhhA+PwDIlstkgSxE= github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9 h1:kyf9snWXHvQc+yxE9imhdI8YAm4oKeZISlaAR+x73zs= github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= @@ -478,23 +386,18 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= -github.com/rootless-containers/rootlesskit v0.7.1 h1:enhwHIAXDjfpV83bL4xF60WZ+1ATjMB7spDDvpWAfPk= -github.com/rootless-containers/rootlesskit v0.7.1/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA= github.com/rootless-containers/rootlesskit v0.7.2 h1:gcWQ9/GN98ne1AqnoeOgQ8e6qpKd3BuB4ug+2h95Fr0= github.com/rootless-containers/rootlesskit v0.7.2/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4 h1:rOG9oHVIndNR14f3HRyBy9UPQYmIPniWqTU1TDdHhq4= github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA= github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f h1:OtU/w6sBKmXYaw2KEODxjcYi3oPSyyslhgGFgIJVGAI= github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA= @@ -515,7 +418,6 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -525,7 +427,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -536,8 +437,6 @@ github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmD github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/theckman/go-flock v0.7.1/go.mod h1:kjuth3y9VJ2aNlkNEO99G/8lp9fMIKaGyBmh84IBheM= github.com/u-root/u-root v5.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY= -github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCIv5XgCsF+kai1NnnrJzEU= -github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 h1:CwmGyzHTzCqCdZJkWR0A7ucZXgrCY7spRcpvm7ci//s= @@ -552,24 +451,17 @@ github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b h1:hdDRrn9OP/roL8a/e/5Z github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b/go.mod h1:YHaw8N660ESgMgLOZfLQqT1htFItynAUxMesFBho52s= github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE= github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= -github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tLAD8IceomUCNw= -github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU= -github.com/vbauerster/mpb/v4 v4.11.1 h1:ZOYQSVHgmeanXsbyC44aDg76tBGCS/54Rk8VkL8dJGA= github.com/vbauerster/mpb/v4 v4.11.1/go.mod h1:vMLa1J/ZKC83G2lB/52XpqT+ZZtFG4aZOdKhmpRL1uM= github.com/vbauerster/mpb/v4 v4.11.2 h1:ynkUoKzi65DZ1UsQPx7sgi/KN6G9f7br+Us2nKm35AM= github.com/vbauerster/mpb/v4 v4.11.2/go.mod h1:jIuIRCltGJUnm6DCyPVkwjlLUk4nHTH+m4eD14CdFF0= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I= github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -580,7 +472,6 @@ github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66/go.mod h1:anY github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -594,7 +485,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4= golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -621,7 +511,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= @@ -632,7 +521,6 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7O golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= @@ -647,7 +535,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190425145619-16072639606e h1:4ktJgTV34+N3qOZUc5fAaG3Pb11qzMm3PkAoTAgUZ2I= golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -655,14 +542,11 @@ golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -670,7 +554,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2 h1:/J2nHFg1MTqaRLFO7M+J78ASNsJoz3r0cvHBPQ77fsE= golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -714,9 +597,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -730,35 +611,25 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v0.0.0-20190624233834-05ebafbffc79/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= -k8s.io/api v0.0.0-20190813020757-36bff7324fb7 h1:4uJOjRn9kWq4AqJRE8+qzmAy+lJd9rh8TY455dNef4U= -k8s.io/api v0.0.0-20190813020757-36bff7324fb7/go.mod h1:3Iy+myeAORNCLgjd/Xu9ebwN7Vh59Bw0vh9jhoX+V58= -k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.17.2 h1:NF1UFXcKN7/OOv1uxdRz3qfra8AHsPav5M93hlV9+Dc= k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010 h1:pyoq062NftC1y/OcnbSvgolyZDJ8y4fmUPWMkdA6gfU= -k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8= -k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.17.2 h1:hwDQQFbdRlpnnsR64Asdi55GyCaIP/3WQpMmbNBeWr4= k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.3 h1:f+uZV6rm4/tHE7xXgLyToprg6xWairaClGVkm2t8omg= +k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= k8s.io/client-go v0.0.0-20170217214107-bcde30fb7eae/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= -k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083 h1:+Qf/nITucAbm09aIdxvoA+7X0BwaXmQGVoR8k7Ynk9o= k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab h1:E8Fecph0qbNsAbijJJQryKu4Oi9QTp5cVpjTE+nqg6g= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= @@ -768,12 +639,9 @@ k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c= -k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= -k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 78ec09f29..216bbe669 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1383,18 +1383,34 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) } if vol.state.NeedsCopyUp { logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name()) + + // Set NeedsCopyUp to false immediately, so we don't try this + // again when there are already files copied. + vol.state.NeedsCopyUp = false + if err := vol.save(); err != nil { + return nil, err + } + + // If the volume is not empty, we should not copy up. + volMount := vol.MountPoint() + contents, err := ioutil.ReadDir(volMount) + if err != nil { + return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID()) + } + if len(contents) > 0 { + // The volume is not empty. It was likely modified + // outside of Podman. For safety, let's not copy up into + // it. Fixes CVE-2020-1726. + return vol, nil + } + srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest) if err != nil { return nil, errors.Wrapf(err, "error calculating destination path to copy up container %s volume %s", c.ID(), vol.Name()) } - if err := c.copyWithTarFromImage(srcDir, vol.MountPoint()); err != nil && !os.IsNotExist(err) { + if err := c.copyWithTarFromImage(srcDir, volMount); err != nil && !os.IsNotExist(err) { return nil, errors.Wrapf(err, "error copying content from container %s into volume %s", c.ID(), vol.Name()) } - - vol.state.NeedsCopyUp = false - if err := vol.save(); err != nil { - return nil, err - } } return vol, nil } diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go index 3ff6210d9..19f7eee1e 100644 --- a/libpod/image/image_test.go +++ b/libpod/image/image_test.go @@ -18,7 +18,6 @@ import ( var ( bbNames = []string{"docker.io/library/busybox:latest", "docker.io/library/busybox", "docker.io/busybox:latest", "docker.io/busybox", "busybox:latest", "busybox"} bbGlibcNames = []string{"docker.io/library/busybox:glibc", "docker.io/busybox:glibc", "busybox:glibc"} - fedoraNames = []string{"registry.fedoraproject.org/fedora-minimal:latest", "registry.fedoraproject.org/fedora-minimal", "fedora-minimal:latest", "fedora-minimal"} ) type localImageTest struct { @@ -139,7 +138,6 @@ func TestImage_New(t *testing.T) { ir.Eventer = events.NewNullEventer() // Build the list of pull names names = append(names, bbNames...) - names = append(names, fedoraNames...) writer := os.Stdout // Iterate over the names and delete the image diff --git a/pkg/api/Makefile b/pkg/api/Makefile index c68e50011..6b24bfd83 100644 --- a/pkg/api/Makefile +++ b/pkg/api/Makefile @@ -9,4 +9,4 @@ validate: ${SWAGGER_OUT} ${SWAGGER_OUT}: # generate doesn't remove file on error rm -f ${SWAGGER_OUT} - swagger generate spec -o ${SWAGGER_OUT} -i tags.yaml -w ./ + swagger generate spec -o ${SWAGGER_OUT} -i tags.yaml -w ./ -m diff --git a/pkg/api/handlers/containers.go b/pkg/api/handlers/containers.go index f180fbc2b..d7d040ce2 100644 --- a/pkg/api/handlers/containers.go +++ b/pkg/api/handlers/containers.go @@ -41,10 +41,9 @@ func StopContainer(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, errors.Wrapf(err, "unable to get state for Container %s", name)) return } - // If the Container is stopped already, send a 302 + // If the Container is stopped already, send a 304 if state == define.ContainerStateStopped || state == define.ContainerStateExited { - utils.Error(w, http.StatusText(http.StatusNotModified), http.StatusNotModified, - errors.Errorf("Container %s is already stopped ", name)) + utils.WriteResponse(w, http.StatusNotModified, "") return } @@ -134,8 +133,7 @@ func StartContainer(w http.ResponseWriter, r *http.Request) { return } if state == define.ContainerStateRunning { - msg := fmt.Sprintf("Container %s is already running", name) - utils.Error(w, msg, http.StatusNotModified, errors.New(msg)) + utils.WriteResponse(w, http.StatusNotModified, "") return } if err := con.Start(r.Context(), false); err != nil { diff --git a/pkg/api/handlers/events.go b/pkg/api/handlers/events.go index 44bf35254..22dad9923 100644 --- a/pkg/api/handlers/events.go +++ b/pkg/api/handlers/events.go @@ -1,19 +1,24 @@ package handlers import ( + "encoding/json" "fmt" "net/http" - "strings" - "time" + "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func GetEvents(w http.ResponseWriter, r *http.Request) { + var ( + fromStart bool + eventsError error + ) query := struct { - Since time.Time `schema:"since"` - Until time.Time `schema:"until"` + Since string `schema:"since"` + Until string `schema:"until"` Filters map[string][]string `schema:"filters"` }{} if err := decodeQuery(r, &query); err != nil { @@ -27,15 +32,30 @@ func GetEvents(w http.ResponseWriter, r *http.Request) { } } - libpodEvents, err := getRuntime(r).GetEvents(libpodFilters) - if err != nil { - utils.BadRequest(w, "filters", strings.Join(r.URL.Query()["filters"], ", "), err) + if len(query.Since) > 0 || len(query.Until) > 0 { + fromStart = true + } + eventChannel := make(chan *events.Event) + go func() { + readOpts := events.ReadOptions{FromStart: fromStart, Stream: true, Filters: libpodFilters, EventChannel: eventChannel, Since: query.Since, Until: query.Until} + eventsError = getRuntime(r).Events(readOpts) + }() + if eventsError != nil { + utils.InternalServerError(w, eventsError) return } - - var apiEvents = make([]*Event, len(libpodEvents)) - for _, v := range libpodEvents { - apiEvents = append(apiEvents, EventToApiEvent(v)) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + for event := range eventChannel { + e := EventToApiEvent(event) + //utils.WriteJSON(w, http.StatusOK, e) + coder := json.NewEncoder(w) + coder.SetEscapeHTML(true) + if err := coder.Encode(e); err != nil { + logrus.Errorf("unable to write json: %q", err) + } + if flusher, ok := w.(http.Flusher); ok { + flusher.Flush() + } } - utils.WriteJSON(w, http.StatusOK, apiEvents) } diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go index f8804b5c0..cbc1be2f0 100644 --- a/pkg/api/handlers/generic/containers_stats.go +++ b/pkg/api/handlers/generic/containers_stats.go @@ -19,9 +19,6 @@ import ( const DefaultStatsPeriod = 5 * time.Second func StatsContainer(w http.ResponseWriter, r *http.Request) { - // 200 no error - // 404 no such - // 500 internal runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 54acdbd36..e11e26510 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -1,16 +1,20 @@ package libpod import ( - "fmt" "net/http" + "path/filepath" + "sort" "strconv" + "time" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/gorilla/schema" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) func StopContainer(w http.ResponseWriter, r *http.Request) { @@ -46,12 +50,13 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { } func ListContainers(w http.ResponseWriter, r *http.Request) { var ( - filters []string + filterFuncs []libpod.ContainerFilter + pss []ListContainer ) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { All bool `schema:"all"` - Filter map[string][]string `schema:"filter"` + Filters map[string][]string `schema:"filters"` Last int `schema:"last"` Namespace bool `schema:"namespace"` Pod bool `schema:"pod"` @@ -66,6 +71,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } + runtime := r.Context().Value("runtime").(*libpod.Runtime) opts := shared.PsOptions{ All: query.All, @@ -73,20 +79,55 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { Size: query.Size, Sort: "", Namespace: query.Namespace, + NoTrunc: true, Pod: query.Pod, Sync: query.Sync, } - if len(query.Filter) > 0 { - for k, v := range query.Filter { + if len(query.Filters) > 0 { + for k, v := range query.Filters { for _, val := range v { - filters = append(filters, fmt.Sprintf("%s=%s", k, val)) + generatedFunc, err := shared.GenerateContainerFilterFuncs(k, val, runtime) + if err != nil { + utils.InternalServerError(w, err) + return + } + filterFuncs = append(filterFuncs, generatedFunc) } } } - pss, err := shared.GetPsContainerOutput(runtime, opts, filters, 2) + + if !query.All { + // The default is get only running containers. Do this with a filterfunc + runningOnly, err := shared.GenerateContainerFilterFuncs("status", define.ContainerStateRunning.String(), runtime) + if err != nil { + utils.InternalServerError(w, err) + return + } + filterFuncs = append(filterFuncs, runningOnly) + } + + cons, err := runtime.GetContainers(filterFuncs...) if err != nil { utils.InternalServerError(w, err) } + if query.Last > 0 { + // Sort the containers we got + sort.Sort(psSortCreateTime{cons}) + // we should perform the lopping before we start getting + // the expensive information on containers + if query.Last < len(cons) { + cons = cons[len(cons)-query.Last:] + } + } + for _, con := range cons { + listCon, err := ListContainerBatch(runtime, con, opts) + if err != nil { + utils.InternalServerError(w, err) + return + } + pss = append(pss, listCon) + + } utils.WriteResponse(w, http.StatusOK, pss) } @@ -194,3 +235,122 @@ func ShowMountedContainers(w http.ResponseWriter, r *http.Request) { } utils.WriteResponse(w, http.StatusOK, response) } + +// BatchContainerOp is used in ps to reduce performance hits by "batching" +// locks. +func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts shared.PsOptions) (ListContainer, error) { + var ( + conConfig *libpod.ContainerConfig + conState define.ContainerStatus + err error + exitCode int32 + exited bool + pid int + size *shared.ContainerSize + startedTime time.Time + exitedTime time.Time + cgroup, ipc, mnt, net, pidns, user, uts string + ) + + batchErr := ctr.Batch(func(c *libpod.Container) error { + conConfig = c.Config() + conState, err = c.State() + if err != nil { + return errors.Wrapf(err, "unable to obtain container state") + } + + exitCode, exited, err = c.ExitCode() + if err != nil { + return errors.Wrapf(err, "unable to obtain container exit code") + } + startedTime, err = c.StartedTime() + if err != nil { + logrus.Errorf("error getting started time for %q: %v", c.ID(), err) + } + exitedTime, err = c.FinishedTime() + if err != nil { + logrus.Errorf("error getting exited time for %q: %v", c.ID(), err) + } + + if !opts.Size && !opts.Namespace { + return nil + } + + if opts.Namespace { + pid, err = c.PID() + if err != nil { + return errors.Wrapf(err, "unable to obtain container pid") + } + ctrPID := strconv.Itoa(pid) + cgroup, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup")) + ipc, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc")) + mnt, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt")) + net, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net")) + pidns, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid")) + user, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user")) + uts, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts")) + } + if opts.Size { + size = new(shared.ContainerSize) + + rootFsSize, err := c.RootFsSize() + if err != nil { + logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err) + } + + rwSize, err := c.RWSize() + if err != nil { + logrus.Errorf("error getting rw size for %q: %v", c.ID(), err) + } + + size.RootFsSize = rootFsSize + size.RwSize = rwSize + } + return nil + }) + + if batchErr != nil { + return ListContainer{}, batchErr + } + + ps := ListContainer{ + Command: conConfig.Command, + Created: conConfig.CreatedTime.Unix(), + Exited: exited, + ExitCode: exitCode, + ExitedAt: exitedTime.Unix(), + ID: conConfig.ID, + Image: conConfig.RootfsImageName, + IsInfra: conConfig.IsInfra, + Labels: conConfig.Labels, + Mounts: ctr.UserVolumes(), + Names: []string{conConfig.Name}, + Pid: pid, + Pod: conConfig.Pod, + Ports: conConfig.PortMappings, + Size: size, + StartedAt: startedTime.Unix(), + State: conState.String(), + } + if opts.Pod && len(conConfig.Pod) > 0 { + pod, err := rt.GetPod(conConfig.Pod) + if err != nil { + return ListContainer{}, err + } + ps.PodName = pod.Name() + } + + if opts.Namespace { + ns := ListContainerNamespaces{ + Cgroup: cgroup, + IPC: ipc, + MNT: mnt, + NET: net, + PIDNS: pidns, + User: user, + UTS: uts, + } + ps.Namespaces = ns + } + return ps, nil +} diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 6c926c45b..bcbe4977e 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -1,15 +1,23 @@ package libpod import ( + "context" "fmt" + "io" "io/ioutil" "net/http" "os" "strconv" + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/image/v5/types" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/containers/libpod/pkg/util" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -176,16 +184,205 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { } func ImagesLoad(w http.ResponseWriter, r *http.Request) { - //TODO ... - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/load is not yet implemented")) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Reference string `schema:"reference"` + }{ + // Add defaults here once needed. + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + return + } + defer os.Remove(tmpfile.Name()) + defer tmpfile.Close() + + if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + return + } + + tmpfile.Close() + loadedImage, err := runtime.LoadImage(context.Background(), query.Reference, tmpfile.Name(), os.Stderr, "") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image")) + return + } + + utils.WriteResponse(w, http.StatusOK, []handlers.LibpodImagesLoadReport{{ID: loadedImage}}) } func ImagesImport(w http.ResponseWriter, r *http.Request) { - //TODO ... - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/import is not yet implemented")) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Changes []string `schema:"changes"` + Message string `schema:"message"` + Reference string `schema:"reference"` + URL string `schema:"URL"` + }{ + // Add defaults here once needed. + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + // Check if we need to load the image from a URL or from the request's body. + source := query.URL + if len(query.URL) == 0 { + tmpfile, err := ioutil.TempFile("", "libpod-images-import.tar") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + return + } + defer os.Remove(tmpfile.Name()) + defer tmpfile.Close() + + if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + return + } + + tmpfile.Close() + source = tmpfile.Name() + } + + importedImage, err := runtime.Import(context.Background(), source, query.Reference, query.Changes, query.Message, true) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import image")) + return + } + + utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage}) } func ImagesPull(w http.ResponseWriter, r *http.Request) { - //TODO ... - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/pull is not yet implemented")) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Reference string `schema:"reference"` + Credentials string `schema:"credentials"` + OverrideOS string `schema:"overrideOS"` + OverrideArch string `schema:"overrideArch"` + TLSVerify bool `schema:"tlsVerify"` + AllTags bool `schema:"allTags"` + }{ + TLSVerify: true, + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + if len(query.Reference) == 0 { + utils.InternalServerError(w, errors.New("reference parameter cannot be empty")) + return + } + // Enforce the docker transport. This is just a precaution as some callers + // might accustomed to using the "transport:reference" notation. Using + // another than the "docker://" transport does not really make sense for a + // remote case. For loading tarballs, the load and import endpoints should + // be used. + imageRef, err := alltransports.ParseImageName(query.Reference) + if err == nil && imageRef.Transport().Name() != docker.Transport.Name() { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Errorf("reference %q must be a docker reference", query.Reference)) + return + } else if err != nil { + origErr := err + imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), query.Reference)) + if err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(origErr, "reference %q must be a docker reference", query.Reference)) + return + } + } + + // all-tags doesn't work with a tagged reference, so let's check early + namedRef, err := reference.Parse(query.Reference) + if err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "error parsing reference %q", query.Reference)) + return + } + if _, isTagged := namedRef.(reference.Tagged); isTagged && query.AllTags { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Errorf("reference %q must not have a tag for all-tags", query.Reference)) + return + } + + var registryCreds *types.DockerAuthConfig + if len(query.Credentials) != 0 { + creds, err := util.ParseRegistryCreds(query.Credentials) + if err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "error parsing credentials %q", query.Credentials)) + return + } + registryCreds = creds + } + + // Setup the registry options + dockerRegistryOptions := image.DockerRegistryOptions{ + DockerRegistryCreds: registryCreds, + OSChoice: query.OverrideOS, + ArchitectureChoice: query.OverrideArch, + } + if query.TLSVerify { + dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) + } + + // Prepare the images we want to pull + imagesToPull := []string{} + res := []handlers.LibpodImagesPullReport{} + imageName := namedRef.String() + + if !query.AllTags { + imagesToPull = append(imagesToPull, imageName) + } else { + systemContext := image.GetSystemContext("", "", false) + tags, err := docker.GetRepositoryTags(context.Background(), systemContext, imageRef) + if err != nil { + utils.InternalServerError(w, errors.Wrap(err, "error getting repository tags")) + return + } + for _, tag := range tags { + imagesToPull = append(imagesToPull, fmt.Sprintf("%s:%s", imageName, tag)) + } + } + + // Finally pull the images + for _, img := range imagesToPull { + newImage, err := runtime.ImageRuntime().New( + context.Background(), + img, + "", + "", + os.Stderr, + &dockerRegistryOptions, + image.SigningOptions{}, + nil, + util.PullImageAlways) + if err != nil { + utils.InternalServerError(w, errors.Wrapf(err, "error pulling image %q", query.Reference)) + return + } + res = append(res, handlers.LibpodImagesPullReport{ID: newImage.ID()}) + } + + utils.WriteResponse(w, http.StatusOK, res) } diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 091368985..e9297d91b 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -91,7 +91,11 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { pod, err := runtime.NewPod(r.Context(), options...) if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) + http_code := http.StatusInternalServerError + if errors.Cause(err) == define.ErrPodExists { + http_code = http.StatusConflict + } + utils.Error(w, "Something went wrong.", http_code, err) return } utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.CgroupParent()}) @@ -198,8 +202,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) { } } if allContainersStopped { - alreadyStopped := errors.Errorf("pod %s is already stopped", pod.ID()) - utils.Error(w, "Something went wrong", http.StatusNotModified, alreadyStopped) + utils.WriteResponse(w, http.StatusNotModified, "") return } @@ -245,8 +248,7 @@ func PodStart(w http.ResponseWriter, r *http.Request) { } } if allContainersRunning { - alreadyRunning := errors.Errorf("pod %s is already running", pod.ID()) - utils.Error(w, "Something went wrong", http.StatusNotModified, alreadyRunning) + utils.WriteResponse(w, http.StatusNotModified, "") return } if _, err := pod.Start(r.Context()); err != nil { @@ -409,5 +411,5 @@ func PodExists(w http.ResponseWriter, r *http.Request) { utils.PodNotFound(w, name, err) return } - utils.WriteResponse(w, http.StatusOK, "") + utils.WriteResponse(w, http.StatusNoContent, "") } diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go new file mode 100644 index 000000000..aec30ef56 --- /dev/null +++ b/pkg/api/handlers/libpod/swagger.go @@ -0,0 +1,8 @@ +package libpod + +// List Containers +// swagger:response ListContainers +type swagInspectPodResponse struct { + // in:body + Body []ListContainer +} diff --git a/pkg/api/handlers/libpod/types.go b/pkg/api/handlers/libpod/types.go new file mode 100644 index 000000000..0949b2a72 --- /dev/null +++ b/pkg/api/handlers/libpod/types.go @@ -0,0 +1,82 @@ +package libpod + +import ( + "github.com/containers/libpod/cmd/podman/shared" + "github.com/containers/libpod/libpod" + "github.com/cri-o/ocicni/pkg/ocicni" +) + +// Listcontainer describes a container suitable for listing +type ListContainer struct { + // Container command + Command []string + // Container creation time + Created int64 + // If container has exited/stopped + Exited bool + // Time container exited + ExitedAt int64 + // If container has exited, the return code from the command + ExitCode int32 + // The unique identifier for the container + ID string `json:"Id"` + // Container image + Image string + // If this container is a Pod infra container + IsInfra bool + // Labels for container + Labels map[string]string + // User volume mounts + Mounts []string + // The names assigned to the container + Names []string + // Namespaces the container belongs to. Requires the + // namespace boolean to be true + Namespaces ListContainerNamespaces + // The process id of the container + Pid int + // If the container is part of Pod, the Pod ID. Requires the pod + // boolean to be set + Pod string + // If the container is part of Pod, the Pod name. Requires the pod + // boolean to be set + PodName string + // Port mappings + Ports []ocicni.PortMapping + // Size of the container rootfs. Requires the size boolean to be true + Size *shared.ContainerSize + // Time when container started + StartedAt int64 + // State of container + State string +} + +// ListContainer Namespaces contains the identifiers of the container's Linux namespaces +type ListContainerNamespaces struct { + // Mount namespace + MNT string `json:"Mnt,omitempty"` + // Cgroup namespace + Cgroup string `json:"Cgroup,omitempty"` + // IPC namespace + IPC string `json:"Ipc,omitempty"` + // Network namespace + NET string `json:"Net,omitempty"` + // PID namespace + PIDNS string `json:"Pidns,omitempty"` + // UTS namespace + UTS string `json:"Uts,omitempty"` + // User namespace + User string `json:"User,omitempty"` +} + +// sortContainers helps us set-up ability to sort by createTime +type sortContainers []*libpod.Container + +func (a sortContainers) Len() int { return len(a) } +func (a sortContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +type psSortCreateTime struct{ sortContainers } + +func (a psSortCreateTime) Less(i, j int) bool { + return a.sortContainers[i].CreatedTime().Before(a.sortContainers[j].CreatedTime()) +} diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go index bc75777aa..10525bfc7 100644 --- a/pkg/api/handlers/swagger.go +++ b/pkg/api/handlers/swagger.go @@ -1,7 +1,6 @@ package handlers import ( - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/inspect" @@ -104,13 +103,6 @@ type swagDockerTopResponse struct { } } -// List containers -// swagger:response LibpodListContainersResponse -type swagLibpodListContainersResponse struct { - // in:body - Body []shared.PsContainerOutput -} - // Inspect container // swagger:response LibpodInspectContainerResponse type swagLibpodInspectContainerResponse struct { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 6169adb18..f5d9f9ad5 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -33,6 +33,18 @@ type ContainerConfig struct { dockerContainer.Config } +type LibpodImagesLoadReport struct { + ID string `json:"id"` +} + +type LibpodImagesImportReport struct { + ID string `json:"id"` +} + +type LibpodImagesPullReport struct { + ID string `json:"id"` +} + type ImageSummary struct { docker.ImageSummary CreatedTime time.Time `json:"CreatedTime,omitempty"` @@ -49,21 +61,6 @@ type LibpodContainersPruneReport struct { PruneError string `json:"error"` } -type LibpodImagesLoadReport struct { - ID string `json:"id"` - RepoTags []string `json:"repoTags"` -} - -type LibpodImagesImportReport struct { - ID string `json:"id"` - RepoTags []string `json:"repoTags"` -} - -type LibpodImagesPullReport struct { - ID string `json:"id"` - RepoTags []string `json:"repoTags"` -} - type Info struct { docker.Info BuildahVersion string diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 970f93791..44bcc794c 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -23,6 +23,14 @@ func IsLibpodRequest(r *http.Request) bool { // WriteResponse encodes the given value as JSON or string and renders it for http client func WriteResponse(w http.ResponseWriter, code int, value interface{}) { + // RFC2616 explicitly states that the following status codes "MUST NOT + // include a message-body": + switch code { + case http.StatusNoContent, http.StatusNotModified: // 204, 304 + w.WriteHeader(code) + return + } + switch v := value.(type) { case string: w.Header().Set("Content-Type", "text/plain; charset=us-ascii") diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index abae81c38..ed30bc14a 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -610,7 +610,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // - application/json // responses: // 200: - // $ref: "#/responses/LibpodListContainersResponse" + // $ref: "#/responses/ListContainers" // 400: // $ref: "#/responses/BadParamError" // 500: diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go index a32244f4d..090f66323 100644 --- a/pkg/api/server/register_events.go +++ b/pkg/api/server/register_events.go @@ -29,7 +29,7 @@ func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error { // description: JSON encoded map[string][]string of constraints // responses: // 200: - // $ref: "#/responses/ok" + // description: returns a string of json data describing an event // 500: // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents)) diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 4a46b6ee6..f082c5fec 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -639,12 +639,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Load an image (oci-archive or docker-archive) stream. // parameters: // - in: query - // name: change - // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" - // type: string - // - in: query - // name: message - // description: Set commit message for imported image + // name: reference + // description: "Optional Name[:TAG] for the image" // type: string // - in: formData // name: upload @@ -656,6 +652,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // responses: // 200: // $ref: "#/responses/DocsLibpodImagesLoadResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImagesLoad)).Methods(http.MethodPost) @@ -667,17 +665,23 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Import a previously exported tarball as an image. // parameters: // - in: query - // name: change - // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" - // type: string + // name: changes + // description: "Apply the following possible instructions to the created image: CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" + // type: array + // items: + // type: string // - in: query // name: message // description: Set commit message for imported image // type: string // - in: query + // name: reference + // description: "Optional Name[:TAG] for the image" + // type: string + // - in: query // name: url - // description: Specify a URL instead of a tarball - // type: boolean + // description: Load image from the specified URL + // type: string // - in: formData // name: upload // type: file @@ -688,34 +692,50 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // responses: // 200: // $ref: "#/responses/DocsLibpodImagesImportResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost) - // swagger:operation GET /libpod/images/pull libpod libpodImagesPull + // swagger:operation POST /libpod/images/pull libpod libpodImagesPull // --- // tags: // - images - // summary: Import image - // description: Import a previosly exported image as a tarball. + // summary: Pull images + // description: Pull one or more images from a container registry. // parameters: - // - in: query - // name: reference - // description: Mandatory reference to the image (e.g., quay.io/image/name:tag)/ - // type: string - // - in: query - // name: credentials - // description: username:password for the registry. - // type: string - // - in: query - // name: tls-verify - // description: Require TLS verification. - // type: boolean - // default: true + // - in: query + // name: reference + // description: "Mandatory reference to the image (e.g., quay.io/image/name:tag)" + // type: string + // - in: query + // name: credentials + // description: "username:password for the registry" + // type: string + // - in: query + // name: overrideOS + // description: Pull image for the specified operating system. + // type: string + // - in: query + // name: overrideArch + // description: Pull image for the specified architecture. + // type: string + // - in: query + // name: tlsVerify + // description: Require TLS verification. + // type: boolean + // default: true + // - in: query + // name: allTags + // description: Pull all tagged images in the repository. + // type: boolean // produces: // - application/json // responses: // 200: // $ref: "#/responses/DocsLibpodImagesPullResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost) diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go index 5c7b51871..974568d47 100644 --- a/pkg/api/server/register_pods.go +++ b/pkg/api/server/register_pods.go @@ -41,6 +41,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // type: string // 400: // $ref: "#/responses/BadParamError" + // 409: + // description: pod already exists // 500: // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/libpod/pods/prune"), APIHandler(s.Context, libpod.PodPrune)).Methods(http.MethodPost) diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index 7bb0f5481..87b11b716 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -106,6 +106,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li server.RegisterContainersHandlers, server.RegisterDistributionHandlers, server.registerExecHandlers, + server.RegisterEventsHandlers, server.registerHealthCheckHandlers, server.registerImagesHandlers, server.registerInfoHandlers, diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go index 116af9709..f270060a6 100644 --- a/pkg/bindings/connection.go +++ b/pkg/bindings/connection.go @@ -130,7 +130,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, // if more desirable we could use url to form the encoded endpoint with params r := req.URL.Query() for k, v := range queryParams { - r.Add(k, url.QueryEscape(v)) + r.Add(k, v) } req.URL.RawQuery = r.Encode() } @@ -155,18 +155,14 @@ func GetConnectionFromContext(ctx context.Context) (*Connection, error) { return conn, nil } -// FiltersToHTML converts our typical filter format of a +// FiltersToString converts our typical filter format of a // map[string][]string to a query/html safe string. -func FiltersToHTML(filters map[string][]string) (string, error) { +func FiltersToString(filters map[string][]string) (string, error) { lowerCaseKeys := make(map[string][]string) for k, v := range filters { lowerCaseKeys[strings.ToLower(k)] = v } - unsafeString, err := jsoniter.MarshalToString(lowerCaseKeys) - if err != nil { - return "", err - } - return url.QueryEscape(unsafeString), nil + return jsoniter.MarshalToString(lowerCaseKeys) } // IsInformation returns true if the response code is 1xx diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index 334a656d4..04f7f8802 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -5,8 +5,8 @@ import ( "net/http" "strconv" - "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" + lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/containers/libpod/pkg/bindings" ) @@ -15,13 +15,16 @@ import ( // the most recent number of containers. The pod and size booleans indicate that pod information and rootfs // size information should also be included. Finally, the sync bool synchronizes the OCI runtime and // container state. -func List(ctx context.Context, filters map[string][]string, last *int, pod, size, sync *bool) ([]*shared.PsContainerOutput, error) { // nolint:typecheck +func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]lpapiv2.ListContainer, error) { // nolint:typecheck conn, err := bindings.GetConnectionFromContext(ctx) if err != nil { return nil, err } - var images []*shared.PsContainerOutput + var containers []lpapiv2.ListContainer params := make(map[string]string) + if all != nil { + params["all"] = strconv.FormatBool(*all) + } if last != nil { params["last"] = strconv.Itoa(*last) } @@ -35,7 +38,7 @@ func List(ctx context.Context, filters map[string][]string, last *int, pod, size params["sync"] = strconv.FormatBool(*sync) } if filters != nil { - filterString, err := bindings.FiltersToHTML(filters) + filterString, err := bindings.FiltersToString(filters) if err != nil { return nil, err } @@ -43,9 +46,9 @@ func List(ctx context.Context, filters map[string][]string, last *int, pod, size } response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params) if err != nil { - return images, err + return containers, err } - return images, response.Process(nil) + return containers, response.Process(&containers) } // Prune removes stopped and exited containers from local storage. The optional filters can be @@ -62,7 +65,7 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) { } params := make(map[string]string) if filters != nil { - filterString, err := bindings.FiltersToHTML(filters) + filterString, err := bindings.FiltersToString(filters) if err != nil { return nil, err } diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go index deaf93f0e..b19482943 100644 --- a/pkg/bindings/images/images.go +++ b/pkg/bindings/images/images.go @@ -38,7 +38,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*handl params["all"] = strconv.FormatBool(*all) } if filters != nil { - strFilters, err := bindings.FiltersToHTML(filters) + strFilters, err := bindings.FiltersToString(filters) if err != nil { return nil, err } @@ -155,7 +155,7 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) { } params := make(map[string]string) if filters != nil { - stringFilter, err := bindings.FiltersToHTML(filters) + stringFilter, err := bindings.FiltersToString(filters) if err != nil { return nil, err } diff --git a/pkg/bindings/images/search.go b/pkg/bindings/images/search.go index d98ddf18d..58b25425b 100644 --- a/pkg/bindings/images/search.go +++ b/pkg/bindings/images/search.go @@ -26,7 +26,7 @@ func Search(ctx context.Context, term string, limit *int, filters map[string][]s params["limit"] = strconv.Itoa(*limit) } if filters != nil { - stringFilter, err := bindings.FiltersToHTML(filters) + stringFilter, err := bindings.FiltersToString(filters) if err != nil { return nil, err } diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go index a6b74c21d..d079f01c2 100644 --- a/pkg/bindings/pods/pods.go +++ b/pkg/bindings/pods/pods.go @@ -97,7 +97,7 @@ func List(ctx context.Context, filters map[string][]string) (*[]libpod.PodInspec } params := make(map[string]string) if filters != nil { - stringFilter, err := bindings.FiltersToHTML(filters) + stringFilter, err := bindings.FiltersToString(filters) if err != nil { return nil, err } diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go index 15783041f..22cd0b7e0 100644 --- a/pkg/bindings/test/common_test.go +++ b/pkg/bindings/test/common_test.go @@ -16,6 +16,7 @@ import ( const ( defaultPodmanBinaryLocation string = "/usr/bin/podman" alpine string = "docker.io/library/alpine:latest" + busybox string = "docker.io/library/busybox:latest" ) type bindingTest struct { @@ -113,7 +114,38 @@ func (b *bindingTest) startAPIService() *gexec.Session { } func (b *bindingTest) cleanup() { + s := b.runPodman([]string{"stop", "-a", "-t", "0"}) + s.Wait(45) if err := os.RemoveAll(b.tempDirPath); err != nil { fmt.Println(err) } } + +// Pull is a helper function to pull in images +func (b *bindingTest) Pull(name string) { + p := b.runPodman([]string{"pull", name}) + p.Wait(45) +} + +// Run a container and add append the alpine image to it +func (b *bindingTest) RunTopContainer(name *string) { + cmd := []string{"run", "-dt"} + if name != nil { + containerName := *name + cmd = append(cmd, "--name", containerName) + } + cmd = append(cmd, alpine, "top") + p := b.runPodman(cmd) + p.Wait(45) +} + +// StringInSlice returns a boolean based on whether a given +// string is in a given slice +func StringInSlice(s string, sl []string) bool { + for _, val := range sl { + if s == val { + return true + } + } + return false +} diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go index f2dc856b2..fea611601 100644 --- a/pkg/bindings/test/images_test.go +++ b/pkg/bindings/test/images_test.go @@ -2,10 +2,10 @@ package test_bindings import ( "context" - "fmt" "time" "github.com/containers/libpod/pkg/bindings" + "github.com/containers/libpod/pkg/bindings/containers" "github.com/containers/libpod/pkg/bindings/images" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -17,12 +17,12 @@ var _ = Describe("Podman images", func() { //tempdir string //err error //podmanTest *PodmanTestIntegration - bt *bindingTest - s *gexec.Session - connText context.Context - err error - false bool - //true bool = true + bt *bindingTest + s *gexec.Session + connText context.Context + err error + falseFlag bool = false + trueFlag bool = true ) BeforeEach(func() { @@ -34,8 +34,8 @@ var _ = Describe("Podman images", func() { //podmanTest.Setup() //podmanTest.SeedImages() bt = newBindingTest() - p := bt.runPodman([]string{"pull", alpine}) - p.Wait(45) + bt.Pull(alpine) + bt.Pull(busybox) s = bt.startAPIService() time.Sleep(1 * time.Second) connText, err = bindings.NewConnection(bt.sock) @@ -68,28 +68,63 @@ var _ = Describe("Podman images", func() { _, err = images.GetImage(connText, data.ID[0:12], nil) Expect(err).To(BeNil()) - //Inspect by long name should work, it doesnt (yet) i think it needs to be html escaped - _, err = images.GetImage(connText, alpine, nil) - Expect(err).To(BeNil()) + // The test to inspect by long name needs to fixed. + // Inspect by long name should work, it doesnt (yet) i think it needs to be html escaped + // _, err = images.GetImage(connText, alpine, nil) + // Expect(err).To(BeNil()) }) + + // Test to validate the remove image api It("remove image", func() { // Remove invalid image should be a 404 - _, err = images.Remove(connText, "foobar5000", &false) + _, err = images.Remove(connText, "foobar5000", &falseFlag) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", 404)) - _, err := images.GetImage(connText, "alpine", nil) + // Remove an image by name, validate image is removed and error is nil + inspectData, err := images.GetImage(connText, "busybox", nil) + Expect(err).To(BeNil()) + response, err := images.Remove(connText, "busybox", nil) + Expect(err).To(BeNil()) + Expect(inspectData.ID).To(Equal(response[0]["Deleted"])) + inspectData, err = images.GetImage(connText, "busybox", nil) + code, _ = bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", 404)) + + // Start a container with alpine image + var top string = "top" + bt.RunTopContainer(&top) + // we should now have a container called "top" running + containerResponse, err := containers.Inspect(connText, "top", &falseFlag) Expect(err).To(BeNil()) + Expect(containerResponse.Name).To(Equal("top")) - response, err := images.Remove(connText, "alpine", &false) + // try to remove the image "alpine". This should fail since we are not force + // deleting hence image cannot be deleted until the container is deleted. + response, err = images.Remove(connText, "alpine", &falseFlag) + code, _ = bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", 500)) + + // Removing the image "alpine" where force = true + response, err = images.Remove(connText, "alpine", &trueFlag) Expect(err).To(BeNil()) - fmt.Println(response) - // to be continued + // Checking if both the images are gone as well as the container is deleted + inspectData, err = images.GetImage(connText, "busybox", nil) + code, _ = bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", 404)) + + inspectData, err = images.GetImage(connText, "alpine", nil) + code, _ = bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", 404)) + + _, err = containers.Inspect(connText, "top", &falseFlag) + code, _ = bindings.CheckResponseCode(err) + Expect(code).To(BeNumerically("==", 404)) }) - //Tests to validate the image tag command. + // Tests to validate the image tag command. It("tag image", func() { // Validates if invalid image name is given a bad response is encountered. err = images.Tag(connText, "dummy", "demo", "alpine") @@ -107,21 +142,30 @@ var _ = Describe("Podman images", func() { }) - //Test to validate the List images command. + // Test to validate the List images command. It("List image", func() { - //Array to hold the list of images returned + // Array to hold the list of images returned imageSummary, err := images.List(connText, nil, nil) - //There Should be no errors in the response. + // There Should be no errors in the response. Expect(err).To(BeNil()) - //Since in the begin context only one image is created the list context should have only one image - Expect(len(imageSummary)).To(Equal(1)) - - //To be written create a new image and check list count again - //imageSummary, err = images.List(connText, nil, nil) - - //Since in the begin context only one image adding one more image should - ///Expect(len(imageSummary)).To(Equal(2) - + // Since in the begin context two images are created the + // list context should have only 2 images + Expect(len(imageSummary)).To(Equal(2)) + + // Adding one more image. There Should be no errors in the response. + // And the count should be three now. + bt.Pull("busybox:glibc") + imageSummary, err = images.List(connText, nil, nil) + Expect(err).To(BeNil()) + Expect(len(imageSummary)).To(Equal(3)) + + //Validate the image names. + var names []string + for _, i := range imageSummary { + names = append(names, i.RepoTags...) + } + Expect(StringInSlice(alpine, names)).To(BeTrue()) + Expect(StringInSlice(busybox, names)).To(BeTrue()) }) }) diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index 3e678d33a..2b51f4e09 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -122,6 +122,7 @@ func parent() error { logrus.WithError(driverErr).Warn("parent driver exited") } errCh <- driverErr + close(errCh) }() opaque := driver.OpaqueForChild() logrus.Infof("opaque=%+v", opaque) @@ -142,15 +143,12 @@ func parent() error { }() // reexec the child process in the child netns - cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid())) + cmd := exec.Command("/proc/self/exe") cmd.Args = []string{reexecChildKey} cmd.Stdin = childQuitR cmd.Stdout = &logrusWriter{prefix: "child"} cmd.Stderr = cmd.Stdout cmd.Env = append(os.Environ(), reexecChildEnvOpaque+"="+string(opaqueJSON)) - cmd.SysProcAttr = &syscall.SysProcAttr{ - Pdeathsig: syscall.SIGTERM, - } childNS, err := ns.GetNS(cfg.NetNSPath) if err != nil { return err @@ -162,14 +160,27 @@ func parent() error { return err } + defer func() { + if err := syscall.Kill(cmd.Process.Pid, syscall.SIGTERM); err != nil { + logrus.WithError(err).Warn("kill child process") + } + }() + logrus.Info("waiting for initComplete") // wait for the child to connect to the parent - select { - case <-initComplete: - logrus.Infof("initComplete is closed; parent and child established the communication channel") - case err := <-errCh: - return err +outer: + for { + select { + case <-initComplete: + logrus.Infof("initComplete is closed; parent and child established the communication channel") + break outer + case err := <-errCh: + if err != nil { + return err + } + } } + defer func() { logrus.Info("stopping parent driver") quit <- struct{}{} diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go new file mode 100644 index 000000000..dcf255378 --- /dev/null +++ b/pkg/seccomp/seccomp.go @@ -0,0 +1,54 @@ +package seccomp + +import ( + "sort" + + "github.com/pkg/errors" +) + +// ContianerImageLabel is the key of the image annotation embedding a seccomp +// profile. +const ContainerImageLabel = "io.containers.seccomp.profile" + +// Policy denotes a seccomp policy. +type Policy int + +const ( + // PolicyDefault - if set use SecurityConfig.SeccompProfilePath, + // otherwise use the default profile. The SeccompProfilePath might be + // explicitly set by the user. + PolicyDefault Policy = iota + // PolicyImage - if set use SecurityConfig.SeccompProfileFromImage, + // otherwise follow SeccompPolicyDefault. + PolicyImage +) + +// Map for easy lookups of supported policies. +var supportedPolicies = map[string]Policy{ + "": PolicyDefault, + "default": PolicyDefault, + "image": PolicyImage, +} + +// LookupPolicy looksup the corresponding Policy for the specified +// string. If none is found, an errors is returned including the list of +// supported policies. +// +// Note that an empty string resolved to SeccompPolicyDefault. +func LookupPolicy(s string) (Policy, error) { + policy, exists := supportedPolicies[s] + if exists { + return policy, nil + } + + // Sort the keys first as maps are non-deterministic. + keys := []string{} + for k := range supportedPolicies { + if k != "" { + keys = append(keys, k) + } + } + sort.Strings(keys) + + return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys) +} diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 32d8cb4de..5f39b6d0d 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strconv" "strings" "github.com/containers/libpod/pkg/rootless" @@ -90,6 +91,42 @@ func devicesFromPath(g *generate.Generator, devicePath string) error { return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":")) } +func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error { + for _, deviceCgroupRule := range deviceCgroupRules { + if err := validateDeviceCgroupRule(deviceCgroupRule); err != nil { + return err + } + ss := parseDeviceCgroupRule(deviceCgroupRule) + if len(ss[0]) != 5 { + return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule) + } + matches := ss[0] + var major, minor *int64 + if matches[2] == "*" { + majorDev := int64(-1) + major = &majorDev + } else { + majorDev, err := strconv.ParseInt(matches[2], 10, 64) + if err != nil { + return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule) + } + major = &majorDev + } + if matches[3] == "*" { + minorDev := int64(-1) + minor = &minorDev + } else { + minorDev, err := strconv.ParseInt(matches[2], 10, 64) + if err != nil { + return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule) + } + minor = &minorDev + } + g.AddLinuxResourcesDevice(true, matches[1], major, minor, matches[4]) + } + return nil +} + func addDevice(g *generate.Generator, device string) error { src, dst, permissions, err := ParseDevice(device) if err != nil { diff --git a/pkg/spec/config_linux_cgo.go b/pkg/spec/config_linux_cgo.go index ae83c9d52..05f42c4da 100644 --- a/pkg/spec/config_linux_cgo.go +++ b/pkg/spec/config_linux_cgo.go @@ -5,9 +5,10 @@ package createconfig import ( "io/ioutil" + "github.com/containers/libpod/pkg/seccomp" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" - seccomp "github.com/seccomp/containers-golang" + goSeccomp "github.com/seccomp/containers-golang" "github.com/sirupsen/logrus" ) @@ -15,9 +16,9 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu var seccompConfig *spec.LinuxSeccomp var err error - if config.SeccompPolicy == SeccompPolicyImage && config.SeccompProfileFromImage != "" { + if config.SeccompPolicy == seccomp.PolicyImage && config.SeccompProfileFromImage != "" { logrus.Debug("Loading seccomp profile from the security config") - seccompConfig, err = seccomp.LoadProfile(config.SeccompProfileFromImage, configSpec) + seccompConfig, err = goSeccomp.LoadProfile(config.SeccompProfileFromImage, configSpec) if err != nil { return nil, errors.Wrap(err, "loading seccomp profile failed") } @@ -30,13 +31,13 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu if err != nil { return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath) } - seccompConfig, err = seccomp.LoadProfile(string(seccompProfile), configSpec) + seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec) if err != nil { return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath) } } else { logrus.Debug("Loading default seccomp profile") - seccompConfig, err = seccomp.GetDefaultProfile(configSpec) + seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec) if err != nil { return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath) } diff --git a/pkg/spec/config_unsupported.go b/pkg/spec/config_unsupported.go index a2c7f4416..be3e7046d 100644 --- a/pkg/spec/config_unsupported.go +++ b/pkg/spec/config_unsupported.go @@ -30,3 +30,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott func devicesFromPath(g *generate.Generator, devicePath string) error { return errors.New("function not implemented") } + +func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error { + return errors.New("function not implemented") +} diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index fb222083b..8010be0d4 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -2,7 +2,6 @@ package createconfig import ( "os" - "sort" "strconv" "strings" "syscall" @@ -11,6 +10,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/namespaces" + "github.com/containers/libpod/pkg/seccomp" "github.com/containers/storage" "github.com/docker/go-connections/nat" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -38,6 +38,7 @@ type CreateResourceConfig struct { CPUs float64 // cpus CPUsetCPUs string CPUsetMems string // cpuset-mems + DeviceCgroupRules []string //device-cgroup-rule DeviceReadBps []string // device-read-bps DeviceReadIOps []string // device-read-iops DeviceWriteBps []string // device-write-bps @@ -107,48 +108,6 @@ type NetworkConfig struct { PublishAll bool //publish-all } -// SeccompPolicy determines which seccomp profile gets applied to the container. -type SeccompPolicy int - -const ( - // SeccompPolicyDefault - if set use SecurityConfig.SeccompProfilePath, - // otherwise use the default profile. The SeccompProfilePath might be - // explicitly set by the user. - SeccompPolicyDefault SeccompPolicy = iota - // SeccompPolicyImage - if set use SecurityConfig.SeccompProfileFromImage, - // otherwise follow SeccompPolicyDefault. - SeccompPolicyImage -) - -// Map for easy lookups of supported policies. -var supportedSeccompPolicies = map[string]SeccompPolicy{ - "": SeccompPolicyDefault, - "default": SeccompPolicyDefault, - "image": SeccompPolicyImage, -} - -// LookupSeccompPolicy looksup the corresponding SeccompPolicy for the specified -// string. If none is found, an errors is returned including the list of -// supported policies. -// Note that an empty string resolved to SeccompPolicyDefault. -func LookupSeccompPolicy(s string) (SeccompPolicy, error) { - policy, exists := supportedSeccompPolicies[s] - if exists { - return policy, nil - } - - // Sort the keys first as maps are non-deterministic. - keys := []string{} - for k := range supportedSeccompPolicies { - if k != "" { - keys = append(keys, k) - } - } - sort.Strings(keys) - - return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys) -} - // SecurityConfig configures the security features for the container type SecurityConfig struct { CapAdd []string // cap-add @@ -158,7 +117,7 @@ type SecurityConfig struct { ApparmorProfile string //SecurityOpts SeccompProfilePath string //SecurityOpts SeccompProfileFromImage string // seccomp profile from the container image - SeccompPolicy SeccompPolicy + SeccompPolicy seccomp.Policy SecurityOpts []string Privileged bool //privileged ReadOnlyRootfs bool //read-only diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go index 6fa0b0636..a5dfccdb9 100644 --- a/pkg/spec/parse.go +++ b/pkg/spec/parse.go @@ -2,12 +2,17 @@ package createconfig import ( "fmt" + "regexp" "strconv" "strings" "github.com/docker/go-units" + "github.com/pkg/errors" ) +// deviceCgroupRulegex defines the valid format of device-cgroup-rule +var deviceCgroupRuleRegex = regexp.MustCompile(`^([acb]) ([0-9]+|\*):([0-9]+|\*) ([rwm]{1,3})$`) + // Pod signifies a kernel namespace is being shared // by a container with the pod it is associated with const Pod = "pod" @@ -205,3 +210,16 @@ func IsValidDeviceMode(mode string) bool { } return true } + +// validateDeviceCgroupRule validates the format of deviceCgroupRule +func validateDeviceCgroupRule(deviceCgroupRule string) error { + if !deviceCgroupRuleRegex.MatchString(deviceCgroupRule) { + return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule) + } + return nil +} + +// parseDeviceCgroupRule matches and parses the deviceCgroupRule into slice +func parseDeviceCgroupRule(deviceCgroupRule string) [][]string { + return deviceCgroupRuleRegex.FindAllStringSubmatch(deviceCgroupRule, -1) +} diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index cae055bb0..b2a152a2d 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -232,6 +232,12 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM return nil, err } } + if len(config.Resources.DeviceCgroupRules) != 0 { + if err := deviceCgroupRules(&g, config.Resources.DeviceCgroupRules); err != nil { + return nil, err + } + addedResources = true + } } // SECURITY OPTS diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index e87ec534c..a54063260 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -27,7 +27,8 @@ t GET /nonesuch 404 t POST /nonesuch '' 404 t GET container/nonesuch/json 404 t GET libpod/containers/nonesuch/json 404 -t GET 'libpod/containers/json?a=b' 400 + +#### FIXME: maybe someday: t GET 'libpod/containers/json?a=b' 400 # Method not allowed t POST /_ping '' 405 diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 243b35e9f..42ec028d0 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -6,9 +6,9 @@ # FIXME: API doesn't support pull yet, so use podman podman pull -q $IMAGE -# We want the SHA without the "sha256:" prefix -full_iid=$(podman images --no-trunc --format '{{.ID}}' $IMAGE) -iid=${full_iid##sha256:} +t GET libpod/images/json 200 \ + .[0].Id~[0-9a-f]\\{64\\} +iid=$(jq -r '.[0].Id' <<<"$output") t GET libpod/images/$iid/exists 204 t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/exists 204 diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 5f0a145f0..a69e8cc99 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -11,18 +11,22 @@ podman pull $IMAGE &>/dev/null # Ensure clean slate podman rm -a -f &>/dev/null -t GET libpod/containers/json 200 [] +t GET libpod/containers/json 200 length=0 podman run $IMAGE true -t GET libpod/containers/json 200 \ - .[0].ID~[0-9a-f]\\{12\\} \ +t GET libpod/containers/json 200 length=0 + +t GET libpod/containers/json?all=true 200 \ + length=1 \ + .[0].Id~[0-9a-f]\\{12\\} \ .[0].Image=$IMAGE \ - .[0].Command=true \ - .[0].State=4 \ + .[0].Command[0]="true" \ + .[0].State=exited \ + .[0].ExitCode=0 \ .[0].IsInfra=false -cid=$(jq -r '.[0].ID' <<<"$output") +cid=$(jq -r '.[0].Id' <<<"$output") t DELETE libpod/containers/$cid 204 diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index 1c25a3822..705de94d2 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -3,19 +3,31 @@ # test pod-related endpoints # +# FIXME! Shouldn't /create give an actual pod ID? +expected_id='machine.slice' +if rootless; then + expected_id=/libpod_parent +fi + t GET libpod/pods/json 200 null -t POST libpod/pods/create name=foo 201 '{"id":"machine.slice"}' # FIXME! +t POST libpod/pods/create name=foo 201 .id=$expected_id t GET libpod/pods/foo/exists 204 t GET libpod/pods/notfoo/exists 404 t GET libpod/pods/foo/json 200 .Config.name=foo .Containers=null t GET libpod/pods/json 200 .[0].Config.name=foo .[0].Containers=null -# Cannot create a dup pod with the same name (FIXME: should that be 409?) -t POST libpod/pods/create name=foo 500 .cause="pod already exists" +# Cannot create a dup pod with the same name +t POST libpod/pods/create name=foo 409 .cause="pod already exists" #t POST libpod/pods/create a=b 400 .cause='bad parameter' # FIXME: unimplemented -t POST libpod/pods/foo/pause '' 204 +if root; then + t POST libpod/pods/foo/pause '' 204 +else + t POST libpod/pods/foo/pause '' 500 \ + .cause="this container does not have a cgroup" \ + .message~".*pause pods containing rootless containers with cgroup V1" +fi t POST libpod/pods/foo/unpause '' 200 t POST libpod/pods/foo/unpause '' 200 # (2nd time) t POST libpod/pods/foo/stop '' 304 diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 786c976d6..fffd7b085 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -41,6 +41,9 @@ echo 0 >$failures_file # Where the tests live TESTS_DIR=$(realpath $(dirname $0)) +# Path to podman binary +PODMAN_BIN=${PODMAN:-${TESTS_DIR}/../../bin/podman} + # END setup ############################################################################### # BEGIN infrastructure code - the helper functions used in tests themselves @@ -97,7 +100,7 @@ function _show_ok() { local green= local reset= local bold= - if [ -t 3 ]; then + if [ -t 1 ]; then red='\e[31m' green='\e[32m' reset='\e[0m' @@ -107,16 +110,16 @@ function _show_ok() { _bump $testcounter_file count=$(<$testcounter_file) if [ $ok -eq 1 ]; then - echo -e "${green}ok $count $testname${reset}" >&3 + echo -e "${green}ok $count $testname${reset}" return fi # Failed local expect=$3 local actual=$4 - echo -e "${red}not ok $count $testname${reset}" >&3 - echo -e "${red}# expected: $expect${reset}" >&3 - echo -e "${red}# actual: ${bold}$actual${reset}" >&3 + echo -e "${red}not ok $count $testname${reset}" + echo -e "${red}# expected: $expect${reset}" + echo -e "${red}# actual: ${bold}$actual${reset}" _bump $failures_file } @@ -201,17 +204,28 @@ function t() { output=$(< $WORKDIR/curl.result.out) + # Special case: 204/304, by definition, MUST NOT return content (rfc2616) + if [[ $expected_code = 204 || $expected_code = 304 ]]; then + if [ -n "$*" ]; then + die "Internal error: ${expected_code} status returns no output; fix your test." + fi + if [ -n "$output" ]; then + _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" + fi + return + fi + for i; do case "$i" in # Exact match on json field - .*=*) + *=*) json_field=$(expr "$i" : "\([^=]*\)=") expect=$(expr "$i" : '[^=]*=\(.*\)') actual=$(jq -r "$json_field" <<<"$output") is "$actual" "$expect" "$testname : $json_field" ;; # regex match on json field - .*~*) + *~*) json_field=$(expr "$i" : "\([^~]*\)~") expect=$(expr "$i" : '[^~]*~\(.*\)') actual=$(jq -r "$json_field" <<<"$output") @@ -231,35 +245,51 @@ function t() { service_pid= function start_service() { # If there's a listener on the port, nothing for us to do - echo -n >/dev/tcp/$HOST/$PORT &>/dev/null && return + { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null && return + + test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" if [ "$HOST" != "localhost" ]; then die "Cannot start service on non-localhost ($HOST)" fi - if [ $(id -u) -ne 0 ]; then - echo "$ME: WARNING: running service rootless is unlikely to work!" >&2 - fi - - # Find the binary - SERVICE_BIN=${SERVICE_BIN:-${TESTS_DIR}/../../bin/service} - test -x $SERVICE_BIN || die "Not found: $SERVICE_BIN" - - systemd-socket-activate -l 127.0.0.1:$PORT \ - $SERVICE_BIN --root $WORKDIR/root \ + $PODMAN_BIN --root $WORKDIR system service --timeout 15000 tcp:127.0.0.1:$PORT \ &> $WORKDIR/server.log & service_pid=$! # Wait local _timeout=5 while [ $_timeout -gt 0 ]; do - echo -n >/dev/tcp/$HOST/$PORT &>/dev/null && return + { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null && return sleep 1 _timeout=$(( $_timeout - 1 )) done die "Timed out waiting for service" } +############ +# podman # Needed by some test scripts to invoke the actual podman binary +############ +function podman() { + echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log + $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1 +} + +#################### +# root, rootless # Is server rootless? +#################### +ROOTLESS= +function root() { + ! rootless +} + +function rootless() { + if [[ -z $ROOTLESS ]]; then + ROOTLESS=$(curl -s http://$HOST:$PORT/v1.40/info | jq .Rootless) + fi + test "$ROOTLESS" = "true" +} + # END infrastructure code ############################################################################### # BEGIN sanity checks @@ -288,10 +318,6 @@ else tests_to_run=($TESTS_DIR/*.at) fi -# Because subtests may run podman or other commands that emit stderr; -# redirect all those and use fd 3 for all output -exec 3>&1 &>$WORKDIR/output.log - start_service for i in ${tests_to_run[@]}; do @@ -304,22 +330,17 @@ done # Clean up if [ -n "$service_pid" ]; then - # Yep, has to be -9. It ignores everything else. - kill -9 $service_pid + kill $service_pid + wait -f $service_pid fi test_count=$(<$testcounter_file) failure_count=$(<$failures_file) -if [ $failure_count -gt 0 -a -s "$WORKDIR/output.log" ]; then - echo "# Collected stdout/stderr:" >&3 - sed -e 's/^/# /' < $WORKDIR/output.log >&3 -fi - if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then rm -rf $WORKDIR fi -echo "1..${test_count}" >&3 +echo "1..${test_count}" exit $failure_count diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index e9d274649..d4503d5a8 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -115,6 +115,25 @@ var _ = Describe("Podman commit", func() { Expect(foundBlue).To(Equal(true)) }) + It("podman commit container with change flag and JSON entrypoint with =", func() { + test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"}) + test.WaitWithDefaultTimeout() + Expect(test.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session := podmanTest.Podman([]string{"commit", "--change", `ENTRYPOINT ["foo", "bar=baz"]`, "test1", "foobar.com/test1-image:latest"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"}) + check.WaitWithDefaultTimeout() + data := check.InspectImageJSON() + Expect(len(data)).To(Equal(1)) + Expect(len(data[0].Config.Entrypoint)).To(Equal(2)) + Expect(data[0].Config.Entrypoint[0]).To(Equal("foo")) + Expect(data[0].Config.Entrypoint[1]).To(Equal("bar=baz")) + }) + It("podman commit container with change CMD flag", func() { test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"}) test.WaitWithDefaultTimeout() diff --git a/test/e2e/config.go b/test/e2e/config.go index 96cc157be..95b0481b3 100644 --- a/test/e2e/config.go +++ b/test/e2e/config.go @@ -2,7 +2,7 @@ package integration var ( redis = "docker.io/library/redis:alpine" - fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest" + fedoraMinimal = "quay.io/libpod/fedora-minimal:latest" ALPINE = "docker.io/library/alpine:latest" ALPINELISTTAG = "docker.io/library/alpine:3.10.2" ALPINELISTDIGEST = "docker.io/library/alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb" diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go index 9ff358d26..9a2cee9e1 100644 --- a/test/e2e/load_test.go +++ b/test/e2e/load_test.go @@ -205,7 +205,7 @@ var _ = Describe("Podman load", func() { podmanTest.RestoreArtifact(fedoraMinimal) outfile := filepath.Join(podmanTest.TempDir, "load_test.tar.gz") - setup := podmanTest.PodmanNoCache([]string{"tag", "fedora-minimal", "hello"}) + setup := podmanTest.PodmanNoCache([]string{"tag", fedoraMinimal, "hello"}) setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 72547ea00..3eb93b84a 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -999,4 +999,16 @@ USER mail` session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) }) + + It("podman run --device-cgroup-rule", func() { + SkipIfRemote() + SkipIfRootless() + deviceCgroupRule := "c 42:* rwm" + session := podmanTest.Podman([]string{"run", "--name", "test", "-d", "--device-cgroup-rule", deviceCgroupRule, ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"exec", "test", "mknod", "newDev", "c", "42", "1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 0c2389e40..46c27dc2e 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -397,4 +397,28 @@ var _ = Describe("Podman run with volumes", func() { volMount.WaitWithDefaultTimeout() Expect(volMount.ExitCode()).To(Not(Equal(0))) }) + + It("Podman fix for CVE-2020-1726", func() { + volName := "testVol" + volCreate := podmanTest.Podman([]string{"volume", "create", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate.ExitCode()).To(Equal(0)) + + volPath := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{.Mountpoint}}", volName}) + volPath.WaitWithDefaultTimeout() + Expect(volPath.ExitCode()).To(Equal(0)) + path := volPath.OutputToString() + + fileName := "thisIsATestFile" + file, err := os.Create(filepath.Join(path, fileName)) + Expect(err).To(BeNil()) + defer file.Close() + + runLs := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "-v", fmt.Sprintf("%v:/etc/ssl", volName), ALPINE, "ls", "-1", "/etc/ssl"}) + runLs.WaitWithDefaultTimeout() + Expect(runLs.ExitCode()).To(Equal(0)) + outputArr := runLs.OutputToStringArray() + Expect(len(outputArr)).To(Equal(1)) + Expect(strings.Contains(outputArr[0], fileName)).To(BeTrue()) + }) }) diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go index 78aa957ab..f1634b6f0 100644 --- a/test/endpoint/endpoint.go +++ b/test/endpoint/endpoint.go @@ -29,7 +29,7 @@ var ( infra = "k8s.gcr.io/pause:3.1" BB = "docker.io/library/busybox:latest" redis = "docker.io/library/redis:alpine" - fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest" + fedoraMinimal = "quay.io/libpod/fedora-minimal:latest" ) type EndpointTestIntegration struct { diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index 92e422eed..35eea9f10 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -1,11 +1,10 @@ # gorilla/mux [![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) [![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux) [![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) -![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png) +![Gorilla Logo](https://cloud-cdn.questionable.services/gorilla-icon-64.png) https://www.gorillatoolkit.org/pkg/mux @@ -26,6 +25,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv * [Examples](#examples) * [Matching Routes](#matching-routes) * [Static Files](#static-files) +* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.) * [Registered URLs](#registered-urls) * [Walking Routes](#walking-routes) * [Graceful Shutdown](#graceful-shutdown) @@ -212,6 +212,93 @@ func main() { } ``` +### Serving Single Page Applications + +Most of the time it makes sense to serve your SPA on a separate web server from your API, +but sometimes it's desirable to serve them both from one place. It's possible to write a simple +handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage +mux's powerful routing for your API endpoints. + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" +) + +// spaHandler implements the http.Handler interface, so we can use it +// to respond to HTTP requests. The path to the static directory and +// path to the index file within that static directory are used to +// serve the SPA in the given static directory. +type spaHandler struct { + staticPath string + indexPath string +} + +// ServeHTTP inspects the URL path to locate a file within the static dir +// on the SPA handler. If a file is found, it will be served. If not, the +// file located at the index path on the SPA handler will be served. This +// is suitable behavior for serving an SPA (single page application). +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // get the absolute path to prevent directory traversal + path, err := filepath.Abs(r.URL.Path) + if err != nil { + // if we failed to get the absolute path respond with a 400 bad request + // and stop + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // prepend the path with the path to the static directory + path = filepath.Join(h.staticPath, path) + + // check whether a file exists at the given path + _, err = os.Stat(path) + if os.IsNotExist(err) { + // file does not exist, serve index.html + http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath)) + return + } else if err != nil { + // if we got an error (that wasn't that the file doesn't exist) stating the + // file, return a 500 internal server error and stop + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static dir + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + +func main() { + router := mux.NewRouter() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + // an example API handler + json.NewEncoder(w).Encode(map[string]bool{"ok": true}) + }) + + spa := spaHandler{staticPath: "build", indexPath: "index.html"} + router.PathPrefix("/").Handler(spa) + + srv := &http.Server{ + Handler: router, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + ### Registered URLs Now let's see how to build registered URLs. diff --git a/vendor/github.com/gorilla/mux/context.go b/vendor/github.com/gorilla/mux/context.go deleted file mode 100644 index 665940a26..000000000 --- a/vendor/github.com/gorilla/mux/context.go +++ /dev/null @@ -1,18 +0,0 @@ -package mux - -import ( - "context" - "net/http" -) - -func contextGet(r *http.Request, key interface{}) interface{} { - return r.Context().Value(key) -} - -func contextSet(r *http.Request, key, val interface{}) *http.Request { - if val == nil { - return r - } - - return r.WithContext(context.WithValue(r.Context(), key, val)) -} diff --git a/vendor/github.com/gorilla/mux/go.mod b/vendor/github.com/gorilla/mux/go.mod index cfc8ede58..df170a399 100644 --- a/vendor/github.com/gorilla/mux/go.mod +++ b/vendor/github.com/gorilla/mux/go.mod @@ -1 +1,3 @@ module github.com/gorilla/mux + +go 1.12 diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go index cf2b26dc0..cb51c565e 100644 --- a/vendor/github.com/gorilla/mux/middleware.go +++ b/vendor/github.com/gorilla/mux/middleware.go @@ -58,22 +58,17 @@ func CORSMethodMiddleware(r *Router) MiddlewareFunc { func getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) { var allMethods []string - err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { - for _, m := range route.matchers { - if _, ok := m.(*routeRegexp); ok { - if m.Match(req, &RouteMatch{}) { - methods, err := route.GetMethods() - if err != nil { - return err - } - - allMethods = append(allMethods, methods...) - } - break + for _, route := range r.routes { + var match RouteMatch + if route.Match(req, &match) || match.MatchErr == ErrMethodMismatch { + methods, err := route.GetMethods() + if err != nil { + return nil, err } + + allMethods = append(allMethods, methods...) } - return nil - }) + } - return allMethods, err + return allMethods, nil } diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index a2cd193e4..c9ba64707 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -5,6 +5,7 @@ package mux import ( + "context" "errors" "fmt" "net/http" @@ -58,8 +59,7 @@ type Router struct { // If true, do not clear the request context after handling the request. // - // Deprecated: No effect when go1.7+ is used, since the context is stored - // on the request itself. + // Deprecated: No effect, since the context is stored on the request itself. KeepContext bool // Slice of middlewares to be called after a match is found @@ -111,10 +111,8 @@ func copyRouteConf(r routeConf) routeConf { c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q)) } - c.matchers = make([]matcher, 0, len(r.matchers)) - for _, m := range r.matchers { - c.matchers = append(c.matchers, m) - } + c.matchers = make([]matcher, len(r.matchers)) + copy(c.matchers, r.matchers) return c } @@ -197,8 +195,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { var handler http.Handler if r.Match(req, &match) { handler = match.Handler - req = setVars(req, match.Vars) - req = setCurrentRoute(req, match.Route) + req = requestWithVars(req, match.Vars) + req = requestWithRoute(req, match.Route) } if handler == nil && match.MatchErr == ErrMethodMismatch { @@ -428,7 +426,7 @@ const ( // Vars returns the route variables for the current request, if any. func Vars(r *http.Request) map[string]string { - if rv := contextGet(r, varsKey); rv != nil { + if rv := r.Context().Value(varsKey); rv != nil { return rv.(map[string]string) } return nil @@ -440,18 +438,20 @@ func Vars(r *http.Request) map[string]string { // after the handler returns, unless the KeepContext option is set on the // Router. func CurrentRoute(r *http.Request) *Route { - if rv := contextGet(r, routeKey); rv != nil { + if rv := r.Context().Value(routeKey); rv != nil { return rv.(*Route) } return nil } -func setVars(r *http.Request, val interface{}) *http.Request { - return contextSet(r, varsKey, val) +func requestWithVars(r *http.Request, vars map[string]string) *http.Request { + ctx := context.WithValue(r.Context(), varsKey, vars) + return r.WithContext(ctx) } -func setCurrentRoute(r *http.Request, val interface{}) *http.Request { - return contextSet(r, routeKey, val) +func requestWithRoute(r *http.Request, route *Route) *http.Request { + ctx := context.WithValue(r.Context(), routeKey, route) + return r.WithContext(ctx) } // ---------------------------------------------------------------------------- diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index ac1abcd47..96dd94ad1 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -181,21 +181,21 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { } } return r.regexp.MatchString(host) - } else { - if r.regexpType == regexpTypeQuery { - return r.matchQueryString(req) - } - path := req.URL.Path - if r.options.useEncodedPath { - path = req.URL.EscapedPath() - } - return r.regexp.MatchString(path) } + + if r.regexpType == regexpTypeQuery { + return r.matchQueryString(req) + } + path := req.URL.Path + if r.options.useEncodedPath { + path = req.URL.EscapedPath() + } + return r.regexp.MatchString(path) } // url builds a URL part using the given values. func (r *routeRegexp) url(values map[string]string) (string, error) { - urlValues := make([]interface{}, len(r.varsN)) + urlValues := make([]interface{}, len(r.varsN), len(r.varsN)) for k, v := range r.varsN { value, ok := values[v] if !ok { @@ -230,14 +230,51 @@ func (r *routeRegexp) getURLQuery(req *http.Request) string { return "" } templateKey := strings.SplitN(r.template, "=", 2)[0] - for key, vals := range req.URL.Query() { - if key == templateKey && len(vals) > 0 { - return key + "=" + vals[0] - } + val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey) + if ok { + return templateKey + "=" + val } return "" } +// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0]. +// If key was not found, empty string and false is returned. +func findFirstQueryKey(rawQuery, key string) (value string, ok bool) { + query := []byte(rawQuery) + for len(query) > 0 { + foundKey := query + if i := bytes.IndexAny(foundKey, "&;"); i >= 0 { + foundKey, query = foundKey[:i], foundKey[i+1:] + } else { + query = query[:0] + } + if len(foundKey) == 0 { + continue + } + var value []byte + if i := bytes.IndexByte(foundKey, '='); i >= 0 { + foundKey, value = foundKey[:i], foundKey[i+1:] + } + if len(foundKey) < len(key) { + // Cannot possibly be key. + continue + } + keyString, err := url.QueryUnescape(string(foundKey)) + if err != nil { + continue + } + if keyString != key { + continue + } + valueString, err := url.QueryUnescape(string(value)) + if err != nil { + continue + } + return valueString, true + } + return "", false +} + func (r *routeRegexp) matchQueryString(req *http.Request) bool { return r.regexp.MatchString(r.getURLQuery(req)) } diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index 8479c68c1..750afe570 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -74,7 +74,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool { return false } - if match.MatchErr == ErrMethodMismatch { + if match.MatchErr == ErrMethodMismatch && r.handler != nil { // We found a route which matches request method, clear MatchErr match.MatchErr = nil // Then override the mis-matched handler @@ -412,11 +412,30 @@ func (r *Route) Queries(pairs ...string) *Route { type schemeMatcher []string func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { - return matchInArray(m, r.URL.Scheme) + scheme := r.URL.Scheme + // https://golang.org/pkg/net/http/#Request + // "For [most] server requests, fields other than Path and RawQuery will be + // empty." + // Since we're an http muxer, the scheme is either going to be http or https + // though, so we can just set it based on the tls termination state. + if scheme == "" { + if r.TLS == nil { + scheme = "http" + } else { + scheme = "https" + } + } + return matchInArray(m, scheme) } // Schemes adds a matcher for URL schemes. // It accepts a sequence of schemes to be matched, e.g.: "http", "https". +// If the request's URL has a scheme set, it will be matched against. +// Generally, the URL scheme will only be set if a previous handler set it, +// such as the ProxyHeaders handler from gorilla/handlers. +// If unset, the scheme will be determined based on the request's TLS +// termination state. +// The first argument to Schemes will be used when constructing a route URL. func (r *Route) Schemes(schemes ...string) *Route { for k, v := range schemes { schemes[k] = strings.ToLower(v) @@ -493,8 +512,8 @@ func (r *Route) Subrouter() *Router { // This also works for host variables: // // r := mux.NewRouter() -// r.Host("{subdomain}.domain.com"). -// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Host("{subdomain}.domain.com"). // Name("article") // // // url.String() will be "http://news.domain.com/articles/technology/42" @@ -502,6 +521,13 @@ func (r *Route) Subrouter() *Router { // "category", "technology", // "id", "42") // +// The scheme of the resulting url will be the first argument that was passed to Schemes: +// +// // url.String() will be "https://example.com" +// r := mux.NewRouter() +// url, err := r.Host("example.com") +// .Schemes("https", "http").URL() +// // All variables defined in the route are required, and their values must // conform to the corresponding patterns. func (r *Route) URL(pairs ...string) (*url.URL, error) { @@ -635,7 +661,7 @@ func (r *Route) GetQueriesRegexp() ([]string, error) { if r.regexp.queries == nil { return nil, errors.New("mux: route doesn't have queries") } - var queries []string + queries := make([]string, 0, len(r.regexp.queries)) for _, query := range r.regexp.queries { queries = append(queries, query.regexp.String()) } @@ -654,7 +680,7 @@ func (r *Route) GetQueriesTemplates() ([]string, error) { if r.regexp.queries == nil { return nil, errors.New("mux: route doesn't have queries") } - var queries []string + queries := make([]string, 0, len(r.regexp.queries)) for _, query := range r.regexp.queries { queries = append(queries, query.template) } diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go index 32ecffde4..5f5c496de 100644 --- a/vendor/github.com/gorilla/mux/test_helpers.go +++ b/vendor/github.com/gorilla/mux/test_helpers.go @@ -15,5 +15,5 @@ import "net/http" // can be set by making a route that captures the required variables, // starting a server and sending the request to that server. func SetURLVars(r *http.Request, val map[string]string) *http.Request { - return setVars(r, val) + return requestWithVars(r, val) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 5c2485f38..a5fd1e65e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -291,7 +291,7 @@ github.com/google/gofuzz github.com/google/shlex # github.com/google/uuid v1.1.1 github.com/google/uuid -# github.com/gorilla/mux v1.7.3 +# github.com/gorilla/mux v1.7.4 github.com/gorilla/mux # github.com/gorilla/schema v1.1.0 github.com/gorilla/schema @@ -632,7 +632,7 @@ gopkg.in/tomb.v1 gopkg.in/yaml.v2 # k8s.io/api v0.17.2 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.17.2 +# k8s.io/apimachinery v0.17.3 k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 |