summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml151
-rw-r--r--Makefile8
-rw-r--r--RELEASE_NOTES.md55
-rw-r--r--changelog.txt118
-rw-r--r--cmd/cli/main.go113
-rw-r--r--cmd/podman/build.go9
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/login.go18
-rw-r--r--cmd/podman/logout.go12
-rw-r--r--cmd/podman/logs.go2
-rw-r--r--cmd/podman/main.go16
-rw-r--r--cmd/podman/pod_create.go17
-rw-r--r--cmd/podman/port.go49
-rw-r--r--cmd/podman/rm.go5
-rw-r--r--cmd/podman/service.go111
-rw-r--r--cmd/podman/shared/container.go8
-rw-r--r--cmd/podman/shared/create.go8
-rw-r--r--cmd/podman/shared/intermediate.go1
-rw-r--r--cni/87-podman-bridge.conflist71
-rw-r--r--completions/bash/podman14
-rwxr-xr-xcontrib/build_rpm.sh9
-rw-r--r--contrib/cirrus/README.md35
-rwxr-xr-xcontrib/cirrus/integration_test.sh27
-rw-r--r--contrib/cirrus/lib.sh24
-rwxr-xr-xcontrib/cirrus/logcollector.sh5
-rw-r--r--contrib/cirrus/packer/Makefile11
-rw-r--r--contrib/cirrus/packer/fedora_setup.sh176
-rw-r--r--contrib/cirrus/packer/image-builder-image_base-setup.sh6
-rw-r--r--contrib/cirrus/packer/libpod_base_images.yml12
-rw-r--r--contrib/cirrus/packer/libpod_images.yml9
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh4
-rwxr-xr-xcontrib/cirrus/setup_environment.sh30
-rwxr-xr-xcontrib/cirrus/unit_test.sh1
-rw-r--r--contrib/spec/podman.spec.in5
-rw-r--r--docs/source/markdown/libpod.conf.5.md3
-rw-r--r--docs/source/markdown/podman-build.1.md17
-rw-r--r--docs/source/markdown/podman-create.1.md21
-rw-r--r--docs/source/markdown/podman-images.1.md8
-rw-r--r--docs/source/markdown/podman-login.1.md7
-rw-r--r--docs/source/markdown/podman-logout.1.md3
-rw-r--r--docs/source/markdown/podman-logs.1.md2
-rw-r--r--docs/source/markdown/podman-pod-create.1.md54
-rw-r--r--docs/source/markdown/podman-ps.1.md3
-rw-r--r--docs/source/markdown/podman-run.1.md7
-rw-r--r--go.mod33
-rw-r--r--go.sum97
-rwxr-xr-xhack/get_ci_vm.sh2
-rw-r--r--libpod/common_test.go1
-rw-r--r--libpod/config/config.go166
-rw-r--r--libpod/config/config_test.go16
-rw-r--r--libpod/config/merge.go183
-rw-r--r--libpod/config/merge_test.go157
-rw-r--r--libpod/container.go8
-rw-r--r--libpod/container_inspect.go100
-rw-r--r--libpod/container_internal.go36
-rw-r--r--libpod/container_internal_linux.go23
-rw-r--r--libpod/container_log_linux.go2
-rw-r--r--libpod/define/errors.go5
-rw-r--r--libpod/image/filters.go11
-rw-r--r--libpod/logs/log.go88
-rw-r--r--libpod/logs/reversereader/reversereader.go66
-rw-r--r--libpod/networking_linux.go132
-rw-r--r--libpod/networking_unsupported.go4
-rw-r--r--libpod/oci_conmon_linux.go10
-rw-r--r--libpod/options.go99
-rw-r--r--libpod/pod.go1
-rw-r--r--libpod/runtime_ctr.go3
-rw-r--r--libpod/runtime_pod_infra_linux.go76
-rw-r--r--libpod/runtime_volume.go3
-rw-r--r--libpod/runtime_volume_linux.go3
-rw-r--r--libpod/util_test.go3
-rw-r--r--libpod/volume.go7
-rw-r--r--pkg/adapter/containers.go39
-rw-r--r--pkg/adapter/pods.go91
-rw-r--r--pkg/adapter/pods_remote.go2
-rw-r--r--pkg/api/handlers/decoder.go13
-rw-r--r--pkg/api/handlers/generic/containers_create.go (renamed from pkg/api/handlers/containers_create.go)34
-rw-r--r--pkg/api/handlers/generic/containers_stats.go16
-rw-r--r--pkg/api/handlers/generic/images.go50
-rw-r--r--pkg/api/handlers/generic/swagger.go6
-rw-r--r--pkg/api/handlers/generic/types.go55
-rw-r--r--pkg/api/handlers/images.go36
-rw-r--r--pkg/api/handlers/libpod/containers_create.go29
-rw-r--r--pkg/api/handlers/libpod/images.go39
-rw-r--r--pkg/api/handlers/libpod/pods.go6
-rw-r--r--pkg/api/handlers/libpod/volumes.go137
-rw-r--r--pkg/api/handlers/types.go51
-rw-r--r--pkg/api/handlers/utils/containers.go27
-rw-r--r--pkg/api/handlers/utils/images.go6
-rw-r--r--pkg/api/server/handler_api.go52
-rw-r--r--pkg/api/server/register_auth.go4
-rw-r--r--pkg/api/server/register_containers.go154
-rw-r--r--pkg/api/server/register_distribution.go2
-rw-r--r--pkg/api/server/register_events.go6
-rw-r--r--pkg/api/server/register_exec.go20
-rw-r--r--pkg/api/server/register_healthcheck.go2
-rw-r--r--pkg/api/server/register_images.go107
-rw-r--r--pkg/api/server/register_info.go2
-rw-r--r--pkg/api/server/register_monitor.go4
-rw-r--r--pkg/api/server/register_ping.go8
-rw-r--r--pkg/api/server/register_plugins.go4
-rw-r--r--pkg/api/server/register_pods.go43
-rw-r--r--pkg/api/server/register_swarm.go2
-rw-r--r--pkg/api/server/register_system.go4
-rw-r--r--pkg/api/server/register_version.go6
-rw-r--r--pkg/api/server/register_volumes.go49
-rw-r--r--pkg/api/server/server.go117
-rw-r--r--pkg/api/server/swagger.go17
-rw-r--r--pkg/bindings/connection.go243
-rw-r--r--pkg/bindings/containers/containers.go69
-rw-r--r--pkg/bindings/containers/create.go30
-rw-r--r--pkg/bindings/containers/healthcheck.go2
-rw-r--r--pkg/bindings/containers/mount.go6
-rw-r--r--pkg/bindings/errors.go2
-rw-r--r--pkg/bindings/images/images.go100
-rw-r--r--pkg/bindings/images/search.go11
-rw-r--r--pkg/bindings/network/network.go6
-rw-r--r--pkg/bindings/pods/pods.go51
-rw-r--r--pkg/bindings/test/common_test.go41
-rw-r--r--pkg/bindings/test/containers_test.go253
-rw-r--r--pkg/bindings/test/images_test.go169
-rw-r--r--pkg/bindings/test/pods_test.go196
-rw-r--r--pkg/bindings/test/volumes_test.go174
-rw-r--r--pkg/bindings/volumes/volumes.go65
-rw-r--r--pkg/network/netconflist.go1
-rw-r--r--pkg/rootless/rootless_linux.c51
-rw-r--r--pkg/rootless/rootless_linux.go2
-rw-r--r--pkg/seccomp/seccomp.go2
-rw-r--r--pkg/spec/config_linux.go18
-rw-r--r--pkg/spec/config_unsupported.go4
-rw-r--r--pkg/spec/createconfig.go8
-rw-r--r--pkg/spec/namespaces.go2
-rw-r--r--pkg/spec/parse.go14
-rw-r--r--pkg/spec/spec.go50
-rw-r--r--pkg/spec/storage.go9
-rw-r--r--pkg/specgen/config_linux_cgo.go62
-rw-r--r--pkg/specgen/config_linux_nocgo.go11
-rw-r--r--pkg/specgen/config_unsupported.go12
-rw-r--r--pkg/specgen/create.go185
-rw-r--r--pkg/specgen/namespaces.go467
-rw-r--r--pkg/specgen/oci.go260
-rw-r--r--pkg/specgen/specgen.go99
-rw-r--r--pkg/specgen/validate.go159
-rw-r--r--pkg/systemd/activation.go40
-rw-r--r--pkg/systemd/generate/systemdgen.go (renamed from pkg/systemdgen/systemdgen.go)2
-rw-r--r--pkg/systemd/generate/systemdgen_test.go (renamed from pkg/systemdgen/systemdgen_test.go)2
-rw-r--r--pkg/util/utils_supported.go4
-rw-r--r--pkg/varlinkapi/pods.go16
-rw-r--r--test/apiv2/01-basic.at15
-rw-r--r--test/apiv2/40-pods.at26
-rwxr-xr-xtest/apiv2/test-apiv22
-rw-r--r--test/e2e/create_staticip_test.go16
-rw-r--r--test/e2e/healthcheck_run_test.go20
-rw-r--r--test/e2e/login_logout_test.go52
-rw-r--r--test/e2e/network_test.go80
-rw-r--r--test/e2e/pod_create_test.go165
-rw-r--r--test/e2e/ps_test.go3
-rw-r--r--test/e2e/run_memory_test.go6
-rw-r--r--test/e2e/run_networking_test.go11
-rw-r--r--test/e2e/run_staticip_test.go16
-rw-r--r--test/e2e/run_test.go16
-rw-r--r--test/e2e/run_volume_test.go20
-rw-r--r--test/e2e/search_test.go22
-rw-r--r--test/system/010-images.bats36
-rw-r--r--test/system/130-kill.bats27
-rw-r--r--test/system/150-login.bats339
-rw-r--r--test/system/500-networking.bats63
-rw-r--r--vendor/github.com/blang/semver/.travis.yml21
-rw-r--r--vendor/github.com/blang/semver/README.md5
-rw-r--r--vendor/github.com/blang/semver/package.json17
-rw-r--r--vendor/github.com/blang/semver/range.go200
-rw-r--r--vendor/github.com/blang/semver/semver.go23
-rw-r--r--vendor/github.com/containers/buildah/.cirrus.yml232
-rw-r--r--vendor/github.com/containers/buildah/.papr.sh42
-rw-r--r--vendor/github.com/containers/buildah/.papr.yml87
-rw-r--r--vendor/github.com/containers/buildah/.travis.yml95
-rw-r--r--vendor/github.com/containers/buildah/CHANGELOG.md52
-rw-r--r--vendor/github.com/containers/buildah/CODE-OF-CONDUCT.md3
-rw-r--r--vendor/github.com/containers/buildah/CONTRIBUTING.md52
-rw-r--r--vendor/github.com/containers/buildah/Makefile12
-rw-r--r--vendor/github.com/containers/buildah/README.md4
-rw-r--r--vendor/github.com/containers/buildah/bors.toml44
-rw-r--r--vendor/github.com/containers/buildah/buildah.go38
-rw-r--r--vendor/github.com/containers/buildah/changelog.txt51
-rw-r--r--vendor/github.com/containers/buildah/chroot/seccomp.go21
-rw-r--r--vendor/github.com/containers/buildah/commit.go31
-rw-r--r--vendor/github.com/containers/buildah/common.go78
-rw-r--r--vendor/github.com/containers/buildah/go.mod37
-rw-r--r--vendor/github.com/containers/buildah/go.sum249
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go27
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/executor.go53
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/stage_executor.go63
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/util.go8
-rw-r--r--vendor/github.com/containers/buildah/info.go3
-rw-r--r--vendor/github.com/containers/buildah/install.md131
-rw-r--r--vendor/github.com/containers/buildah/new.go17
-rw-r--r--vendor/github.com/containers/buildah/pkg/cli/common.go35
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse.go90
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse_unix.go18
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse_unsupported.go4
-rw-r--r--vendor/github.com/containers/buildah/pull.go16
-rw-r--r--vendor/github.com/containers/buildah/run_linux.go58
-rw-r--r--vendor/github.com/containers/buildah/util/util.go72
-rw-r--r--vendor/github.com/containers/buildah/util/util_linux.go20
-rw-r--r--vendor/github.com/containers/buildah/util/util_unsupported.go8
-rw-r--r--vendor/github.com/containers/common/pkg/capabilities/capabilities.go142
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/blkio.go149
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cgroups.go564
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go89
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go14
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cpu.go123
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/cpuset.go85
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/memory.go66
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/pids.go62
-rw-r--r--vendor/github.com/containers/common/pkg/cgroups/systemd.go79
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go885
-rw-r--r--vendor/github.com/containers/common/pkg/config/config_linux.go7
-rw-r--r--vendor/github.com/containers/common/pkg/config/config_unix.go15
-rw-r--r--vendor/github.com/containers/common/pkg/config/config_unsupported.go7
-rw-r--r--vendor/github.com/containers/common/pkg/config/config_windows.go10
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf375
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go346
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_linux.go55
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_unsupported.go13
-rw-r--r--vendor/github.com/containers/common/pkg/config/util_supported.go69
-rw-r--r--vendor/github.com/containers/common/pkg/config/util_windows.go12
-rw-r--r--vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go22
-rw-r--r--vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go11
-rw-r--r--vendor/github.com/containers/common/pkg/unshare/unshare_linux.go35
-rw-r--r--vendor/github.com/containers/storage/CODE-OF-CONDUCT.md3
-rw-r--r--vendor/github.com/containers/storage/Makefile11
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/go.mod4
-rw-r--r--vendor/github.com/containers/storage/go.sum4
-rw-r--r--vendor/github.com/containers/storage/images_ffjson.go2
-rw-r--r--vendor/github.com/containers/storage/layers_ffjson.go2156
-rw-r--r--vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go101
-rw-r--r--vendor/github.com/containers/storage/pkg/homedir/homedir_others.go25
-rw-r--r--vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go15
-rw-r--r--vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go3
-rw-r--r--vendor/github.com/containers/storage/pkg/reexec/command_linux.go15
-rw-r--r--vendor/github.com/containers/storage/store.go7
-rw-r--r--vendor/github.com/containers/storage/utils.go52
-rw-r--r--vendor/github.com/docker/spdystream/connection.go11
-rw-r--r--vendor/github.com/docker/spdystream/handlers.go4
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/.golangci.yaml1
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/.travis.yml1
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/AUTHORS1
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/LICENSE2
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/README.md2
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/appveyor.yml5
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/auth.go9
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/container.go11
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/go.mod6
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/go.sum14
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/swarm_service.go1
-rw-r--r--vendor/github.com/fsouza/go-dockerclient/tls.go1
-rw-r--r--vendor/github.com/ishidawataru/sctp/.travis.yml10
-rw-r--r--vendor/github.com/ishidawataru/sctp/NOTICE3
-rw-r--r--vendor/github.com/ishidawataru/sctp/go.mod3
-rw-r--r--vendor/github.com/ishidawataru/sctp/ipsock_linux.go4
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp.go49
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp_linux.go69
-rw-r--r--vendor/github.com/ishidawataru/sctp/sctp_unsupported.go39
-rw-r--r--vendor/github.com/klauspost/compress/flate/fast_encoder.go24
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go9
-rw-r--r--vendor/github.com/klauspost/compress/flate/level1.go5
-rw-r--r--vendor/github.com/klauspost/compress/flate/level2.go6
-rw-r--r--vendor/github.com/klauspost/compress/flate/level3.go6
-rw-r--r--vendor/github.com/klauspost/compress/flate/level4.go4
-rw-r--r--vendor/github.com/klauspost/compress/flate/level5.go3
-rw-r--r--vendor/github.com/klauspost/compress/flate/level6.go3
-rw-r--r--vendor/github.com/klauspost/compress/flate/stateless.go67
-rw-r--r--vendor/github.com/mattn/go-shellwords/util_go15.go29
-rw-r--r--vendor/github.com/mattn/go-shellwords/util_posix.go7
-rw-r--r--vendor/github.com/mattn/go-shellwords/util_windows.go7
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go123
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go70
-rw-r--r--vendor/github.com/spf13/cobra/.gitignore5
-rw-r--r--vendor/github.com/spf13/cobra/.travis.yml9
-rw-r--r--vendor/github.com/spf13/cobra/README.md105
-rw-r--r--vendor/github.com/spf13/cobra/bash_completions.go15
-rw-r--r--vendor/github.com/spf13/cobra/cobra.go4
-rw-r--r--vendor/github.com/spf13/cobra/command.go49
-rw-r--r--vendor/github.com/spf13/cobra/go.mod5
-rw-r--r--vendor/github.com/spf13/cobra/go.sum120
-rw-r--r--vendor/github.com/stretchr/testify/assert/assertion_format.go78
-rw-r--r--vendor/github.com/stretchr/testify/assert/assertion_forward.go156
-rw-r--r--vendor/github.com/stretchr/testify/assert/assertions.go218
-rw-r--r--vendor/github.com/stretchr/testify/assert/forward_assertions.go2
-rw-r--r--vendor/github.com/stretchr/testify/require/forward_requirements.go2
-rw-r--r--vendor/github.com/stretchr/testify/require/require.go210
-rw-r--r--vendor/github.com/stretchr/testify/require/require_forward.go156
-rw-r--r--vendor/github.com/stretchr/testify/require/requirements.go2
-rw-r--r--vendor/github.com/uber/jaeger-lib/metrics/metrics.go2
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/.travis.yml7
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/README.md3
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/draft.go8
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/errors.go104
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/format_checkers.go103
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/go.mod7
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/go.sum11
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/jsonContext.go1
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go42
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/locales.go165
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/result.go37
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/schema.go75
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go3
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/schemaPool.go10
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/subSchema.go117
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/types.go4
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/utils.go61
-rw-r--r--vendor/github.com/xeipuuv/gojsonschema/validation.go199
-rw-r--r--vendor/golang.org/x/crypto/blowfish/block.go159
-rw-r--r--vendor/golang.org/x/crypto/blowfish/cipher.go99
-rw-r--r--vendor/golang.org/x/crypto/blowfish/const.go199
-rw-r--r--vendor/golang.org/x/crypto/openpgp/armor/armor.go21
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_arm.go19
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_arm.s427
-rw-r--r--vendor/golang.org/x/crypto/poly1305/sum_noasm.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/certs.go35
-rw-r--r--vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go93
-rw-r--r--vendor/golang.org/x/crypto/ssh/keys.go474
-rw-r--r--vendor/golang.org/x/crypto/ssh/server.go4
-rw-r--r--vendor/golang.org/x/crypto/ssh/terminal/terminal.go17
-rw-r--r--vendor/golang.org/x/crypto/ssh/terminal/util_windows.go4
-rw-r--r--vendor/golang.org/x/oauth2/oauth2.go2
-rw-r--r--vendor/golang.org/x/time/rate/rate.go17
-rw-r--r--vendor/golang.org/x/xerrors/doc.go23
-rw-r--r--vendor/golang.org/x/xerrors/fmt.go138
-rw-r--r--vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go26
-rw-r--r--vendor/modules.txt49
332 files changed, 14433 insertions, 5408 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 5c4cf470c..371f902c2 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -30,10 +30,9 @@ env:
####
#### Cache-image names to test with (double-quotes around names are critical)
###
- _BUILT_IMAGE_SUFFIX: "libpod-5642998972416000"
- FEDORA_CACHE_IMAGE_NAME: "fedora-30-${_BUILT_IMAGE_SUFFIX}"
+ _BUILT_IMAGE_SUFFIX: "libpod-5874660151656448"
+ FEDORA_CACHE_IMAGE_NAME: "fedora-31-${_BUILT_IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-30-${_BUILT_IMAGE_SUFFIX}"
- SPECIAL_FEDORA_CACHE_IMAGE_NAME: "xfedora-30-${_BUILT_IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-19-${_BUILT_IMAGE_SUFFIX}"
PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-${_BUILT_IMAGE_SUFFIX}"
@@ -143,11 +142,16 @@ 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
+ only_if: >-
+ $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
+ $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*' &&
+ $CIRRUS_BRANCH != $DEST_BRANCH
+
depends_on:
- "gating"
env:
@@ -246,12 +250,8 @@ build_each_commit_task:
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
gce_instance:
- image_project: "libpod-218412"
- zone: "us-central1-a" # Required by Cirrus for the time being
cpu: 8
memory: "8Gb"
- disk: 200
- image_name: "${FEDORA_CACHE_IMAGE_NAME}"
timeout_in: 30m
@@ -279,12 +279,8 @@ build_without_cgo_task:
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
gce_instance:
- image_project: "libpod-218412"
- zone: "us-central1-a" # Required by Cirrus for the time being
cpu: 8
memory: "8Gb"
- disk: 200
- image_name: "${FEDORA_CACHE_IMAGE_NAME}"
timeout_in: 30m
@@ -317,7 +313,6 @@ meta_task:
IMGNAMES: >-
${FEDORA_CACHE_IMAGE_NAME}
${PRIOR_FEDORA_CACHE_IMAGE_NAME}
- ${SPECIAL_FEDORA_CACHE_IMAGE_NAME}
${UBUNTU_CACHE_IMAGE_NAME}
${PRIOR_UBUNTU_CACHE_IMAGE_NAME}
${IMAGE_BUILDER_CACHE_IMAGE_NAME}
@@ -377,8 +372,7 @@ testing_task:
gce_instance:
matrix:
- # Images are generated separately, from build_images_task (below)
- #image_name: "${FEDORA_CACHE_IMAGE_NAME}"
+ image_name: "${FEDORA_CACHE_IMAGE_NAME}"
image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
# Multiple test failures on Ubuntu 19 - Fixes TBD in future PR
# TODO: image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
@@ -416,6 +410,7 @@ testing_task:
audit_log_script: '$SCRIPT_BASE/logcollector.sh audit'
journal_script: '$SCRIPT_BASE/logcollector.sh journal'
varlink_script: '$SCRIPT_BASE/logcollector.sh varlink'
+ podman_system_info_script: '$SCRIPT_BASE/logcollector.sh podman'
# This task executes tests under unique environments/conditions
@@ -466,9 +461,20 @@ special_testing_in_podman_task:
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
+ gce_instance:
+ matrix:
+ # FIXME: Integration testing currently broken for F31 hosts
+ # Error: container_linux.go:345: starting container process caused "process_linux.go:281: applying cgroup configuration for process caused \"mountpoint for cgroup not found\"": OCI runtime error
+ # image_name: "${FEDORA_CACHE_IMAGE_NAME}"
+ image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
+
env:
ADD_SECOND_PARTITION: true
SPECIALMODE: 'in_podman' # See docs
+ # TODO: Support both runc and crun (cgroups v1 and v2 container images)
+ # matrix:
+ # IN_PODMAN_IMAGE: "quay.io/libpod/in_podman:latest"
+ # IN_PODMAN_IMAGE: "quay.io/libpod/in_podman_cgv2:latest"
timeout_in: 60m
@@ -519,7 +525,7 @@ special_testing_cross_task:
type: "application/octet-stream"
-special_testing_cgroupv2_task:
+special_testing_bindings_task:
depends_on:
- "gating"
@@ -530,18 +536,11 @@ special_testing_cgroupv2_task:
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
$CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
- gce_instance:
- image_name: "${SPECIAL_FEDORA_CACHE_IMAGE_NAME}"
-
env:
- SPECIALMODE: 'cgroupv2' # See docs
- matrix:
- TEST_REMOTE_CLIENT: true
- TEST_REMOTE_CLIENT: false
+ SPECIALMODE: 'bindings' # See docs
- timeout_in: 120m
+ timeout_in: 40m
- networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
@@ -578,22 +577,6 @@ special_testing_endpoint_task:
<<: *standardlogs
-test_building_snap_task:
-
- depends_on:
- - "gating"
-
- only_if: >-
- $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
- $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
-
- container:
- image: yakshaveinc/snapcraft:core18
- snapcraft_script:
- - 'apt-get -y update'
- - 'cd contrib/snapcraft && snapcraft'
-
-
# Test building of new cache-images for future PR testing, in this PR.
test_build_cache_images_task:
@@ -652,12 +635,13 @@ verify_test_built_images_task:
matrix:
# Required env. var. by check_image_script
PACKER_BUILDER_NAME: "fedora-30"
- #PACKER_BUILDER_NAME: "fedora-31"
- PACKER_BUILDER_NAME: "xfedora-30"
+ PACKER_BUILDER_NAME: "fedora-31"
PACKER_BUILDER_NAME: "ubuntu-18"
- # TODO support $UBUNTU_CACHE_IMAGE_NAME: PACKER_BUILDER_NAME: "ubuntu-19"
+ # Multiple test failures on ${UBUNTU_CACHE_IMAGE_NAME}
+ # PACKER_BUILDER_NAME: "ubuntu-19"
networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
+ installed_packages_script: '$SCRIPT_BASE/logcollector.sh packages'
environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
# Verify expectations once per image
check_image_script: >-
@@ -666,47 +650,59 @@ verify_test_built_images_task:
# Note: A truncated form of normal testing. It only needs to confirm new images
# "probably" work. A full round of testing will happen again after $*_CACHE_IMAGE_NAME
# are updated in this or another PR (w/o '***CIRRUS: TEST IMAGES***').
- integration_test_script: >-
- [[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
- $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}
+ integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
- system_test_script: >-
- [[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
- $SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}
+ system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
always:
<<: *standardlogs
- #upload_snap_task:
- # only_if: >-
- # $CIRRUS_BRANCH != $DEST_BRANCH &&
- # $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
- # $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
- #
- # # Only when PR or branch is merged into master
- #
- # depends_on:
- # - "test_building_snap"
- #
- # container:
- # image: yakshaveinc/snapcraft:core18
- #
- # env:
- # SNAPCRAFT_LOGIN: ENCRYPTED[d8e82eb31c6372fec07f405f413d57806026b1a9f8400033531ebcd54d6750a5e4a8b1f68e3ec65c98c65e0d9b2a6a75]
- # snapcraft_login_file:
- # path: /root/.snapcraft/login.cfg
- # variable_name: SNAPCRAFT_LOGIN
- # snapcraft_script:
- # - 'apt-get -y update'
- # - 'snapcraft login --with "/root/.snapcraft/login.cfg"'
- # - 'cd contrib/snapcraft && snapcraft && snapcraft push *.snap --release edge'
+
+#test_building_snap_task:
+#
+# depends_on:
+# - "gating"
+#
+# only_if: >-
+# $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
+# $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
+#
+# container:
+# image: yakshaveinc/snapcraft:core18
+# snapcraft_script:
+# - 'apt-get -y update'
+# - 'cd contrib/snapcraft && snapcraft'
+#
+#
+#upload_snap_task:
+# only_if: >-
+# $CIRRUS_BRANCH != $DEST_BRANCH &&
+# $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
+# $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:DOCS.*'
+#
+# # Only when PR or branch is merged into master
+#
+# depends_on:
+# - "test_building_snap"
+#
+# container:
+# image: yakshaveinc/snapcraft:core18
+#
+# env:
+# SNAPCRAFT_LOGIN: ENCRYPTED[d8e82eb31c6372fec07f405f413d57806026b1a9f8400033531ebcd54d6750a5e4a8b1f68e3ec65c98c65e0d9b2a6a75]
+# snapcraft_login_file:
+# path: /root/.snapcraft/login.cfg
+# variable_name: SNAPCRAFT_LOGIN
+# snapcraft_script:
+# - 'apt-get -y update'
+# - 'snapcraft login --with "/root/.snapcraft/login.cfg"'
+# - 'cd contrib/snapcraft && snapcraft && snapcraft push *.snap --release edge'
docs_task:
- # Only run this for PRs on mention, and after merge
- only_if: >-
- $CIRRUS_BRANCH != $DEST_BRANCH
+ # Don't run this when building/testing new VM images
+ only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*'
depends_on:
- "gating"
@@ -736,11 +732,10 @@ success_task:
- "rpmbuild"
- "special_testing_rootless"
- "special_testing_in_podman"
- - "special_testing_cgroupv2"
- "special_testing_cross"
- "special_testing_endpoint"
+ - "special_testing_bindings"
- "test_build_cache_images"
- - "test_building_snap"
- "verify_test_built_images"
- "docs"
diff --git a/Makefile b/Makefile
index 67e798c8d..95b5e04d3 100644
--- a/Makefile
+++ b/Makefile
@@ -151,7 +151,7 @@ endif
lint: golangci-lint
@echo "Linting vs commit '$(call err_if_empty,EPOCH_TEST_COMMIT)'"
ifeq ($(PRE_COMMIT),)
- @echo "FATAL: pre-commit was not found, check https://pre-commit.com/ about installing it." >&2
+ @echo "FATAL: pre-commit was not found, make .install.pre-commit to installing it." >&2
@exit 2
endif
$(PRE_COMMIT) run -a
@@ -562,6 +562,12 @@ endef
.install.golangci-lint: .gopathok
VERSION=1.18.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
+.PHONY: .install.pre-commit
+.install.pre-commit:
+ if [ -z "$(PRE_COMMIT)" ]; then \
+ python3 -m pip install --user pre-commit; \
+ fi
+
.PHONY: .install.md2man
.install.md2man: .gopathok
if [ ! -x "$(GOMD2MAN)" ]; then \
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index fc528d70f..f813b494f 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,60 @@
# Release Notes
+## 1.8.1
+### Features
+- Many networking-related flags have been added to `podman pod create` to enable customization of pod networks, including `--add-host`, `--dns`, `--dns-opt`, `--dns-search`, `--ip`, `--mac-address`, `--network`, and `--no-hosts`
+- The `podman ps --format=json` command now includes the ID of the image containers were created with
+- The `podman create` and `podman run` commands now support the `--device-cgroup-rule` flag ([#4876](https://github.com/containers/libpod/issues/4876))
+- While the HTTP API remains in alpha, many fixes and additions have landed. These are documented in a separate subsection below
+- The `podman create` and `podman run` commands now feature a `--no-healthcheck` flag to disable healthchecks for a container ([#5299](https://github.com/containers/libpod/issues/5299))
+
+### Bugfixes
+- Fixed CVE-2020-1726, a security issue where volumes manually populated before first being mounted into a container could have those contents overwritten on first being mounted into a container
+- Fixed a bug where Podman containers with user namespaces in CNI networks with the DNS plugin enabled would not have the DNS plugin's nameserver added to their `resolv.conf` ([#5256](https://github.com/containers/libpod/issues/5256))
+- Fixed a bug where trailing `/` characters in image volume definitions could cause them to not be overridden by a user-specified mount at the same location ([#5219](https://github.com/containers/libpod/issues/5219))
+- Fixed a bug where the `label` option in `libpod.conf`, used to disable SELinux by default, was not being respected ([#5087](https://github.com/containers/libpod/issues/5087))
+- Fixed a bug where the `podman login` and `podman logout` commands required the registry to log into be specified ([#5146](https://github.com/containers/libpod/issues/5146))
+- Fixed a bug where detached rootless Podman containers could not forward ports ([#5167](https://github.com/containers/libpod/issues/5167))
+- Fixed a bug where rootless Podman could fail to run if the pause process had died
+- Fixed a bug where Podman ignored labels that were specified with only a key and no value ([#3854](https://github.com/containers/libpod/issues/3854))
+- Fixed a bug where Podman would fail to create named volumes when the backing filesystem did not support SELinux labelling ([#5200](https://github.com/containers/libpod/issues/5200))
+- Fixed a bug where `--detach-keys=""` would not disable detaching from a container ([#5166](https://github.com/containers/libpod/issues/5166))
+- Fixed a bug where the `podman ps` command was too aggressive when filtering containers and would force `--all` on in too many situations
+- Fixed a bug where the `podman play kube` command was ignoring image configuration, including volumes, working directory, labels, and stop signal ([#5174](https://github.com/containers/libpod/issues/5174))
+- Fixed a bug where the `Created` and `CreatedTime` fields in `podman images --format=json` were misnamed, which also broke Go template output for those fields ([#5110](https://github.com/containers/libpod/issues/5110))
+- Fixed a bug where rootless Podman containers with ports forwarded could hang when started ([#5182](https://github.com/containers/libpod/issues/5182))
+- Fixed a bug where `podman pull` could fail to parse registry names including port numbers
+- Fixed a bug where Podman would incorrectly attempt to validate image OS and architecture when starting containers
+- Fixed a bug where Bash completion for `podman build -f` would not list available files that could be built ([#3878](https://github.com/containers/libpod/issues/3878))
+- Fixed a bug where `podman commit --change` would perform incorrect validation, resulting in valid changes being rejected ([#5148](https://github.com/containers/libpod/issues/5148))
+- Fixed a bug where `podman logs --tail` could take large amounts of memory when the log file for a container was large ([#5131](https://github.com/containers/libpod/issues/5131))
+- Fixed a bug where Podman would sometimes incorrectly generate firewall rules on systems using `firewalld`
+- Fixed a bug where the `podman inspect` command would not display network information for containers properly if a container joined multiple CNI networks ([#4907](https://github.com/containers/libpod/issues/4907))
+- Fixed a bug where the `--uts` flag to `podman create` and `podman run` would only allow specifying containers by full ID ([#5289](https://github.com/containers/libpod/issues/5289))
+- Fixed a bug where rootless Podman could segfault when passed a large number of file descriptors
+- Fixed a bug where the `podman port` command was incorrectly interpreting additional arguments as container names, instead of port numbers
+
+### HTTP API
+- Initial support for secure connections to servers via SSH tunneling has been added
+- Initial support for the libpod `create` and `logs` endpoints for containers has been added
+- Added a `/swagger/` endpoint to serve API documentation
+- The `json` endpoint for containers has received many fixes
+- Filtering images and containers has been greatly improved, with many bugs fixed and documentation improved
+- Image creation endpoints (commit, pull, etc) have seen many fixes
+- Server timeout has been fixed so that long operations will no longer trigger the timeout and shut the server down
+- The `stats` endpoint for containers has seen major fixes and now provides accurate output
+- Handling the HTTP 304 status code has been fixed for all endpoints
+- Many fixes have been made to API documentation to ensure it matches the code
+
+### Misc
+- Updated vendored Buildah to v1.14.1
+- Updated vendored containers/storage to v1.16.0
+- The `Created` field to `podman images --format=json` has been renamed to `CreatedSince` as part of the fix for ([#5110](https://github.com/containers/libpod/issues/5110)). Go templates using the old name should still work
+- The `CreatedTime` field to `podman images --format=json` has been renamed to `CreatedAt` as part of the fix for ([#5110](https://github.com/containers/libpod/issues/5110)). Go templates using the old name should still work
+- The `before` filter to `podman images` has been renamed to `since` for Docker compatibility. Using `before` will still work, but documentation has been changed to use the new `since` filter
+- Using the `--password` flag to `podman login` now warns that passwords are being passed in plaintext
+- Some common cases where Podman would deadlock have been fixed to warn the user that `podman system renumber` must be run to resolve the deadlock
+
## 1.8.0
### Features
- The `podman system service` command has been added, providing a preview of Podman's new Docker-compatible API. This API is still very new, and not yet ready for production use, but is available for early testing
diff --git a/changelog.txt b/changelog.txt
index 320526596..0dac716d0 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,121 @@
+- Changelog for v1.8.1-rc1 (2020-02-21)
+ * Update release notes for v1.8.1
+ * disable generation of cni firewall plugin
+ * search endpoint failure correction
+ * Remove ImageVolumes from database
+ * Upgrade make package-install for fedora31
+ * Flake fix: race condition in same-IP test
+ * Add support for ssh:// and unix:// podman clients
+ * search test on fedora registry: retry 5 times
+ * Swagger: yet more fixes
+ * Login test: use --password-stdin
+ * implement reverse reader for log reads
+ * podman images: add --filter=since=XX
+ * populate resolv.conf with dnsname responses when in usernamespace
+ * Beautify podman bridge CNI config
+ * build(deps): bump github.com/spf13/cobra from 0.0.5 to 0.0.6
+ * Warn user about --password cli option in login
+ * build(deps): bump github.com/stretchr/testify from 1.5.0 to 1.5.1
+ * Swagger: fix one incorrect comment
+ * apiv2 container create using specgen
+ * Add test to validate the pod bindings api
+ * Update to the latest version of buildah
+ * New login and push tests
+ * Add network options to podman pod create
+ * Fixed syscall.Signal not convertable by decoder
+ * Fixed typo in KillContainer
+ * build(deps): bump github.com/containers/storage from 1.15.8 to 1.16.0
+ * build(deps): bump github.com/stretchr/testify from 1.4.0 to 1.5.0
+ * libpod.conf: clarify `label` description
+ * set process labels in pkg/spec
+ * libpod/config: use built-in TOML instead of manually merging
+ * Fixed CreateImageFromImage not respecting supplied Tag parameter
+ * Add installation of pre-commit to Makefile
+ * fix mandatory parameter in login/logout
+ * adds missing query struct tags and exports the fields
+ * Swagger: fix inconsistencies (try #2)
+ * Update mux rules to allow slashes in image names
+ * rootless: fix a regression when using -d
+ * Misc typo fixes
+ * Use cleaned destination path for indexing image volumes
+ * Add ability for pods to use the host network
+ * stats: Expose CPU usage in API
+ * rootless: check if the conmon process is valid
+ * apiv2: Fixup /containers/json filters documentation
+ * apiv2: Enable filtering images by ID
+ * Fix handler and systemd activation errors
+ * podman-ps: support image IDs
+ * Refactor image tree for API usage
+ * Update documentation of commit command to show image reference is optional
+ * Rework label parsing
+ * add caching for binding tests
+ * apiv2 libpod container logs
+ * add pkg/signal
+ * add pkg/capabilities
+ * build(deps): bump github.com/rootless-containers/rootlesskit
+ * Fix SELinux labels of volumes
+ * podman(1): fixes
+ * fix bug "" disable detach keys
+ * Fixed a bug about bash automatically complete
+ * Enhance fuse-overlayfs instructions.
+ * README: fix docs links
+ * Fix up play kube to use image data
+ * build(deps): bump k8s.io/api from 0.17.2 to 0.17.3
+ * Only set --all when a status filter is given to ps
+ * use quay.io/libpod/fedora-minimal for reliability
+ * filtering behavior correction
+ * support device-cgroup-rule
+ * rootlessport: drop Pdeathsig in favor of Kill
+ * rootlessport: fix potential hang
+ * add pkg/seccomp
+ * Do not copy up when volume is not empty
+ * api: pull: fix reference parsing
+ * cmd/podman/pull: refactor code
+ * stats: add SystemUsage
+ * build(deps): bump k8s.io/apimachinery from 0.17.2 to 0.17.3
+ * build(deps): bump github.com/gorilla/mux from 1.7.3 to 1.7.4
+ * HTTP 304 (NotModified) is not an error!
+ * API v2 tests: catch up to moving target
+ * api: fix the CPU stats reported
+ * apiv2 stream events
+ * Fix container filters
+ * API v2: pods: fix two incorrect return codes
+ * Rewire ListContainers for APIv2 libpod
+ * podman build -f completions
+ * swagger: fix /libpod/images/{import,load,pull}
+ * Make: s/uname -o/uname -s/
+ * container create: relax os/arch checks
+ * replace prow images test
+ * Remove incorrect validation of --change for commit
+ * [CI:DOCS] Update Code of Conduct to Containers variant
+ * Add test cases to validate remove and list images api.
+ * images --format compatible with docker
+ * bash-completions: Add missing subcommands in 'podman system'
+ * doc: Fix examples for 'podman system service'
+ * v2 api: /libpod/images/import
+ * v2 api: /libpod/images/load
+ * v2 api: /libpod/images/pull
+ * docs: add workaround for --device with rootless containers (II)
+ * Fix varlink code generation target.
+ * Modify Runtime.getImage to return a storage.Image
+ * Document an aspect of newFromStorage behavior
+ * Introduce a Runtime.newImage constructor
+ * Move Image.getLocalImage to Runtime.getLocalImage
+ * Remove the getLocalImage() call from Image.Size
+ * Use Runtime.NewFromLocal instead of open-coded copies
+ * Trivial simplification
+ * Create two separate newImage instances in Runtime.New
+ * Call NewImageRuntimeFromStore from NewImageRuntimeFromOptions
+ * Update readme to 1.8.0 release
+ * Refactor runtime functions to pass options structure
+ * build(deps): bump github.com/containers/image/v5 from 5.2.0 to 5.2.1
+ * LibpodAPI.BuildImage: don't require a name for the new image
+ * Bump to v1.8.1-dev
+ * Cirrus: Never run prune on other branches
+ * Add dockerfile to mirror fedora-minimal
+ * Add /swagger/ endpoint to serve swagger yaml to clients
+ * Add backend code for pod network options
+
- Changelog for v1.8.0 (2020-02-06)
* [CI:DOCS]update contrib systemd user
* [CI:DOCS]fix systemd files for apiv2
diff --git a/cmd/cli/main.go b/cmd/cli/main.go
deleted file mode 100644
index 4eec05ef2..000000000
--- a/cmd/cli/main.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package main
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "os"
-
- "golang.org/x/crypto/ssh"
-)
-
-// remote PODMAN_HOST=ssh://<user>@<host>[:port]/run/podman/podman.sock
-// local PODMAN_HOST=unix://run/podman/podman.sock
-
-var (
- DefaultURL = "unix://root@localhost/run/podman/podman.sock"
-)
-
-func main() {
- connectionURL := DefaultURL
- if value, found := os.LookupEnv("PODMAN_HOST"); found {
- connectionURL = value
- }
-
- _url, err := url.Parse(connectionURL)
- if err != nil {
- die("Value of PODMAN_HOST is not a valid url: %s\n", connectionURL)
- }
-
- if _url.Scheme != "ssh" && _url.Scheme != "unix" {
- die("Scheme from PODMAN_HOST is not supported: %s\n", _url.Scheme)
- }
-
- // Now we setup the http client to use the connection above
- client := &http.Client{}
- if _url.Scheme == "ssh" {
- var auth ssh.AuthMethod
- if value, found := os.LookupEnv("PODMAN_SSHKEY"); found {
- auth, err = publicKey(value)
- if err != nil {
- die("Failed to parse %s: %v\n", value, err)
- }
- } else {
- die("PODMAN_SSHKEY was not defined\n")
- }
-
- // Connect to sshd
- bastion, err := ssh.Dial("tcp",
- net.JoinHostPort(_url.Hostname(), _url.Port()),
- &ssh.ClientConfig{
- User: _url.User.Username(),
- Auth: []ssh.AuthMethod{auth},
- HostKeyCallback: ssh.InsecureIgnoreHostKey(),
- },
- )
- if err != nil {
- die("Failed to build ssh tunnel")
- }
- defer bastion.Close()
-
- client.Transport = &http.Transport{
- DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
- // Now we make the connection to the unix domain socket on the server using the ssh tunnel
- return bastion.Dial("unix", _url.Path)
- },
- }
- } else {
- client.Transport = &http.Transport{
- DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- d := net.Dialer{}
- return d.DialContext(ctx, "unix", _url.Path)
- },
- DisableCompression: true,
- }
- }
-
- resp, err := client.Get("http://localhost/v1.24/images/json")
- if err != nil {
- die(err.Error())
- }
- defer resp.Body.Close()
- body, _ := ioutil.ReadAll(resp.Body)
-
- var output bytes.Buffer
- _ = json.Indent(&output, body, "", " ")
- fmt.Printf("%s\n", output.String())
- os.Exit(0)
-}
-
-func die(format string, a ...interface{}) {
- fmt.Fprintf(os.Stderr, format, a...)
- fmt.Fprintf(os.Stderr, "\n")
- os.Exit(1)
-}
-
-func publicKey(path string) (ssh.AuthMethod, error) {
- key, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
-
- signer, err := ssh.ParsePrivateKey(key)
- if err != nil {
- return nil, err
- }
-
- return ssh.PublicKeys(signer), nil
-}
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 1fcb98a0e..b8b315c68 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -53,13 +53,12 @@ var (
}
)
-func init() {
+func initBuild() {
buildCommand.Command = _buildCommand
buildCommand.SetHelpTemplate(HelpTemplate())
buildCommand.SetUsageTemplate(UsageTemplate())
flags := buildCommand.Flags()
flags.SetInterspersed(true)
-
budFlags := buildahcli.GetBudFlags(&budFlagsValues)
flag := budFlags.Lookup("pull")
if err := flag.Value.Set("true"); err != nil {
@@ -84,7 +83,10 @@ func init() {
}
flag.DefValue = "true"
- fromAndBugFlags := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues)
+ fromAndBugFlags, err := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues)
+ if err != nil {
+ logrus.Errorf("failed to setup podman build flags: %v", err)
+ }
flags.AddFlagSet(&budFlags)
flags.AddFlagSet(&fromAndBugFlags)
@@ -350,6 +352,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
ContextDirectory: contextDir,
DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile,
Err: stderr,
+ In: os.Stdin,
ForceRmIntermediateCtrs: c.ForceRm,
IIDFile: c.Iidfile,
Labels: c.Label,
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 6fa2b3c71..4eeb09d42 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -396,6 +396,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"Assign a name to the container",
)
createFlags.Bool(
+ "no-healthcheck", false,
+ "Disable healthchecks on container",
+ )
+ createFlags.Bool(
"oom-kill-disable", false,
"Disable OOM Killer",
)
diff --git a/cmd/podman/login.go b/cmd/podman/login.go
index 369e0da16..e09117833 100644
--- a/cmd/podman/login.go
+++ b/cmd/podman/login.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/registries"
"github.com/docker/docker-credential-helpers/credentials"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -67,10 +68,23 @@ func loginCmd(c *cliconfig.LoginValues) error {
if len(args) > 1 {
return errors.Errorf("too many arguments, login takes only 1 argument")
}
+ var server string
if len(args) == 0 {
- return errors.Errorf("please specify a registry to login to")
+ registriesFromFile, err := registries.GetRegistries()
+ if err != nil || len(registriesFromFile) == 0 {
+ return errors.Errorf("please specify a registry to login to")
+ }
+
+ server = registriesFromFile[0]
+ logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", server)
+
+ } else {
+ server = registryFromFullName(scrubServer(args[0]))
+ }
+
+ if c.Flag("password").Changed {
+ fmt.Fprintf(os.Stderr, "WARNING! Using --password via the cli is insecure. Please consider using --password-stdin\n")
}
- server := registryFromFullName(scrubServer(args[0]))
sc := image.GetSystemContext("", c.Authfile, false)
if c.Flag("tls-verify").Changed {
diff --git a/cmd/podman/logout.go b/cmd/podman/logout.go
index 4a113b1d0..dec6822cf 100644
--- a/cmd/podman/logout.go
+++ b/cmd/podman/logout.go
@@ -8,7 +8,9 @@ import (
"github.com/containers/image/v5/pkg/docker/config"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
+ "github.com/containers/libpod/pkg/registries"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -51,10 +53,16 @@ func logoutCmd(c *cliconfig.LogoutValues) error {
if len(args) > 1 {
return errors.Errorf("too many arguments, logout takes at most 1 argument")
}
+ var server string
if len(args) == 0 && !c.All {
- return errors.Errorf("registry must be given")
+ registriesFromFile, err := registries.GetRegistries()
+ if err != nil || len(registriesFromFile) == 0 {
+ return errors.Errorf("no registries found in registries.conf, a registry must be provided")
+ }
+
+ server = registriesFromFile[0]
+ logrus.Debugf("registry not specified, default to the first registry %q from registries.conf", server)
}
- var server string
if len(args) == 1 {
server = scrubServer(args[0])
}
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go
index 4bb26cd07..0a86fa128 100644
--- a/cmd/podman/logs.go
+++ b/cmd/podman/logs.go
@@ -15,7 +15,7 @@ var (
logsCommand cliconfig.LogsValues
logsDescription = `Retrieves logs for one or more containers.
- This does not guarantee execution order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs.
+ This does not guarantee execution order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs).
`
_logsCommand = &cobra.Command{
Use: "logs [flags] CONTAINER [CONTAINER...]",
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index a22b01f24..3320ab72f 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -83,7 +83,7 @@ var rootCmd = &cobra.Command{
var MainGlobalOpts cliconfig.MainFlags
-func init() {
+func initCobra() {
cobra.OnInitialize(initConfig)
rootCmd.TraverseChildren = true
rootCmd.Version = version.Version
@@ -94,16 +94,20 @@ func init() {
rootCmd.AddCommand(getMainCommands()...)
}
-func initConfig() {
- // we can do more stuff in here.
-}
-
-func before(cmd *cobra.Command, args []string) error {
+func init() {
if err := libpod.SetXdgDirs(); err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
+ initBuild()
+ initCobra()
+}
+
+func initConfig() {
+ // we can do more stuff in here.
+}
+func before(cmd *cobra.Command, args []string) error {
// Set log level; if not log-level is provided, default to error
logLevel := MainGlobalOpts.LogLevel
if logLevel == "" {
diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go
index 0f72780f9..810f62f02 100644
--- a/cmd/podman/pod_create.go
+++ b/cmd/podman/pod_create.go
@@ -45,19 +45,7 @@ func init() {
podCreateCommand.SetUsageTemplate(UsageTemplate())
flags := podCreateCommand.Flags()
flags.SetInterspersed(false)
- // When we are ready to add the network options to the create commmand, we need to uncomment
- // the following
-
- //flags.AddFlagSet(getNetFlags())
-
- // Once this is uncommented, then the publish option below needs to be removed because it
- // conflicts with the publish in getNetFlags. Upon removal, the c.Publish will not work
- // anymore and needs to be cleaned up. I suggest starting with removing the Publish attribute
- // from PodCreateValues structure. Running make should then expose all areas that need to be
- // addressed. To get the value of publish (and other flags in getNetFlags, use the syntax:
- // c.<type>("<flag_name") or c.Bool("publish")
- // Remember to do this safely by checking len, etc.
-
+ flags.AddFlagSet(getNetFlags())
flags.StringVar(&podCreateCommand.CgroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
flags.BoolVar(&podCreateCommand.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
flags.StringVar(&podCreateCommand.InfraImage, "infra-image", define.DefaultInfraImage, "The image of the infra container to associate with the pod")
@@ -67,7 +55,6 @@ func init() {
flags.StringVarP(&podCreateCommand.Name, "name", "n", "", "Assign a name to the pod")
flags.StringVarP(&podCreateCommand.Hostname, "hostname", "", "", "Set a hostname to the pod")
flags.StringVar(&podCreateCommand.PodIDFile, "pod-id-file", "", "Write the pod ID to the file")
- flags.StringSliceVarP(&podCreateCommand.Publish, "publish", "p", []string{}, "Publish a container's port, or a range of ports, to the host (default [])")
flags.StringVar(&podCreateCommand.Share, "share", shared.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
}
@@ -83,7 +70,7 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error {
}
defer runtime.DeferredShutdown(false)
- if len(c.Publish) > 0 {
+ if len(c.StringSlice("publish")) > 0 {
if !c.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host")
}
diff --git a/cmd/podman/port.go b/cmd/podman/port.go
index eef3d4b1d..4bb79a3a2 100644
--- a/cmd/podman/port.go
+++ b/cmd/podman/port.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
+ "github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -16,7 +17,7 @@ var (
portDescription = `List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
`
_portCommand = &cobra.Command{
- Use: "port [flags] CONTAINER",
+ Use: "port [flags] CONTAINER [PORT]",
Short: "List port mappings or a specific mapping for the container",
Long: portDescription,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -48,8 +49,8 @@ func init() {
func portCmd(c *cliconfig.PortValues) error {
var (
- userProto string
- userPort int
+ userPort nat.Port
+ err error
)
args := c.InputArgs
@@ -70,25 +71,19 @@ func portCmd(c *cliconfig.PortValues) error {
if len(args) == 1 && c.Latest {
port = args[0]
}
- if port != "" {
+ if len(port) > 0 {
fields := strings.Split(port, "/")
- // User supplied at least port
- var err error
- // User supplied port and protocol
- if len(fields) == 2 {
- userProto = fields[1]
- }
- if len(fields) >= 1 {
- p := fields[0]
- userPort, err = strconv.Atoi(p)
- if err != nil {
- return errors.Wrapf(err, "unable to format port")
- }
- }
- // Format is incorrect
if len(fields) > 2 || len(fields) < 1 {
return errors.Errorf("port formats are port/protocol. '%s' is invalid", port)
}
+ if len(fields) == 1 {
+ fields = append(fields, "tcp")
+ }
+
+ userPort, err = nat.NewPort(fields[1], fields[0])
+ if err != nil {
+ return err
+ }
}
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
@@ -96,7 +91,6 @@ func portCmd(c *cliconfig.PortValues) error {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.DeferredShutdown(false)
-
containers, err := runtime.Port(c)
if err != nil {
return err
@@ -122,17 +116,18 @@ func portCmd(c *cliconfig.PortValues) error {
fmt.Printf("%d/%s -> %s:%d\n", v.ContainerPort, v.Protocol, hostIP, v.HostPort)
continue
}
- // We have a match on ports
- if v.ContainerPort == int32(userPort) {
- if userProto == "" || userProto == v.Protocol {
- fmt.Printf("%s:%d\n", hostIP, v.HostPort)
- found = true
- break
- }
+ containerPort, err := nat.NewPort(v.Protocol, strconv.Itoa(int(v.ContainerPort)))
+ if err != nil {
+ return err
+ }
+ if containerPort == userPort {
+ fmt.Printf("%s:%d\n", hostIP, v.HostPort)
+ found = true
+ break
}
}
if !found && port != "" {
- return errors.Errorf("failed to find published port '%d'", userPort)
+ return errors.Errorf("failed to find published port %q", port)
}
}
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index e69565e95..644b0ef76 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -4,8 +4,10 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -77,6 +79,9 @@ func rmCmd(c *cliconfig.RmValues) error {
if len(failures) > 0 {
for _, err := range failures {
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ logrus.Errorf("Potential deadlock detected - please run 'podman system renumber' to resolve")
+ }
exitCode = setExitCode(err)
}
}
diff --git a/cmd/podman/service.go b/cmd/podman/service.go
index 4978b5d51..7606e3009 100644
--- a/cmd/podman/service.go
+++ b/cmd/podman/service.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/pkg/adapter"
api "github.com/containers/libpod/pkg/api/server"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/systemd"
"github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/pkg/varlinkapi"
"github.com/containers/libpod/version"
@@ -50,21 +51,52 @@ func init() {
serviceCommand.SetHelpTemplate(HelpTemplate())
serviceCommand.SetUsageTemplate(UsageTemplate())
flags := serviceCommand.Flags()
- flags.Int64VarP(&serviceCommand.Timeout, "timeout", "t", 1000, "Time until the service session expires in milliseconds. Use 0 to disable the timeout")
+ flags.Int64VarP(&serviceCommand.Timeout, "timeout", "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
flags.BoolVar(&serviceCommand.Varlink, "varlink", false, "Use legacy varlink service instead of REST")
}
func serviceCmd(c *cliconfig.ServiceValues) error {
- // For V2, default to the REST socket
- apiURI := adapter.DefaultAPIAddress
+ apiURI, err := resolveApiURI(c)
+ if err != nil {
+ return err
+ }
+
+ // Create a single runtime api consumption
+ runtime, err := libpodruntime.GetRuntimeDisableFDs(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "error creating libpod runtime")
+ }
+ defer func() {
+ if err := runtime.Shutdown(false); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to shutdown libpod runtime: %v", err)
+ }
+ }()
+
+ timeout := time.Duration(c.Timeout) * time.Second
if c.Varlink {
- apiURI = adapter.DefaultVarlinkAddress
+ return runVarlink(runtime, apiURI, timeout, c)
}
+ return runREST(runtime, apiURI, timeout)
+}
+
+func resolveApiURI(c *cliconfig.ServiceValues) (string, error) {
+ var apiURI string
- if rootless.IsRootless() {
+ // When determining _*THE*_ listening endpoint --
+ // 1) User input wins always
+ // 2) systemd socket activation
+ // 3) rootless honors XDG_RUNTIME_DIR
+ // 4) if varlink -- adapter.DefaultVarlinkAddress
+ // 5) lastly adapter.DefaultAPIAddress
+
+ if len(c.InputArgs) > 0 {
+ apiURI = c.InputArgs[0]
+ } else if ok := systemd.SocketActivated(); ok {
+ apiURI = ""
+ } else if rootless.IsRootless() {
xdg, err := util.GetRuntimeDir()
if err != nil {
- return err
+ return "", err
}
socketName := "podman.sock"
if c.Varlink {
@@ -74,53 +106,58 @@ func serviceCmd(c *cliconfig.ServiceValues) error {
if _, err := os.Stat(filepath.Dir(socketDir)); err != nil {
if os.IsNotExist(err) {
if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil {
- return err
+ return "", err
}
} else {
- return err
+ return "", err
}
}
- apiURI = fmt.Sprintf("unix:%s", socketDir)
- }
-
- if len(c.InputArgs) > 0 {
- apiURI = c.InputArgs[0]
+ apiURI = "unix:" + socketDir
+ } else if c.Varlink {
+ apiURI = adapter.DefaultVarlinkAddress
+ } else {
+ // For V2, default to the REST socket
+ apiURI = adapter.DefaultAPIAddress
}
- logrus.Infof("using API endpoint: %s", apiURI)
-
- // Create a single runtime api consumption
- runtime, err := libpodruntime.GetRuntimeDisableFDs(getContext(), &c.PodmanCommand)
- if err != nil {
- return errors.Wrapf(err, "error creating libpod runtime")
+ if "" == apiURI {
+ logrus.Info("using systemd socket activation to determine API endpoint")
+ } else {
+ logrus.Infof("using API endpoint: %s", apiURI)
}
- defer runtime.DeferredShutdown(false)
-
- timeout := time.Duration(c.Timeout) * time.Millisecond
- if c.Varlink {
- return runVarlink(runtime, apiURI, timeout, c)
- }
- return runREST(runtime, apiURI, timeout)
+ return apiURI, nil
}
func runREST(r *libpod.Runtime, uri string, timeout time.Duration) error {
logrus.Warn("This function is EXPERIMENTAL")
fmt.Println("This function is EXPERIMENTAL.")
- fields := strings.Split(uri, ":")
- if len(fields) == 1 {
- return errors.Errorf("%s is an invalid socket destination", uri)
- }
- address := strings.Join(fields[1:], ":")
- l, err := net.Listen(fields[0], address)
- if err != nil {
- return errors.Wrapf(err, "unable to create socket %s", uri)
+
+ var listener *net.Listener
+ if uri != "" {
+ fields := strings.Split(uri, ":")
+ if len(fields) == 1 {
+ return errors.Errorf("%s is an invalid socket destination", uri)
+ }
+ address := strings.Join(fields[1:], ":")
+ l, err := net.Listen(fields[0], address)
+ if err != nil {
+ return errors.Wrapf(err, "unable to create socket %s", uri)
+ }
+ listener = &l
}
- defer l.Close()
- server, err := api.NewServerWithSettings(r, timeout, &l)
+ server, err := api.NewServerWithSettings(r, timeout, listener)
if err != nil {
return err
}
- return server.Serve()
+ defer func() {
+ if err := server.Shutdown(); err != nil {
+ fmt.Fprintf(os.Stderr, "Error when stopping service: %s", err)
+ }
+ }()
+
+ err = server.Serve()
+ logrus.Debugf("%d/%d Active connections/Total connections\n", server.ActiveConnections, server.TotalConnections)
+ return err
}
func runVarlink(r *libpod.Runtime, uri string, timeout time.Duration, c *cliconfig.ServiceValues) error {
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index ff3846e70..b5a1e7104 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -30,6 +30,7 @@ import (
const (
cidTruncLength = 12
podTruncLength = 12
+ iidTruncLength = 12
cmdTruncLength = 17
)
@@ -66,6 +67,7 @@ type BatchContainerStruct struct {
type PsContainerOutput struct {
ID string
Image string
+ ImageID string
Command string
Created string
Ports string
@@ -203,7 +205,7 @@ func NewBatchContainer(r *libpod.Runtime, ctr *libpod.Container, opts PsOptions)
status = "Error"
}
- _, imageName := ctr.Image()
+ imageID, imageName := ctr.Image()
cid := ctr.ID()
podID := ctr.PodID()
if !opts.NoTrunc {
@@ -214,6 +216,9 @@ func NewBatchContainer(r *libpod.Runtime, ctr *libpod.Container, opts PsOptions)
if len(command) > cmdTruncLength {
command = command[0:cmdTruncLength] + "..."
}
+ if len(imageID) > iidTruncLength {
+ imageID = imageID[0:iidTruncLength]
+ }
}
ports, err := ctr.PortMappings()
@@ -223,6 +228,7 @@ func NewBatchContainer(r *libpod.Runtime, ctr *libpod.Container, opts PsOptions)
pso.ID = cid
pso.Image = imageName
+ pso.ImageID = imageID
pso.Command = command
pso.Created = created
pso.Ports = portsToString(ports)
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 99538b3dc..0814eeba3 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -120,12 +120,13 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
imageName = newImage.ID()
}
- // if the user disabled the healthcheck with "none", we skip adding it
+ // if the user disabled the healthcheck with "none" or the no-healthcheck
+ // options is provided, we skip adding it
healthCheckCommandInput := c.String("healthcheck-command")
// the user didn't disable the healthcheck but did pass in a healthcheck command
// now we need to make a healthcheck from the commandline input
- if healthCheckCommandInput != "none" {
+ if healthCheckCommandInput != "none" && !c.Bool("no-healthcheck") {
if len(healthCheckCommandInput) > 0 {
healthCheck, err = makeHealthCheckFromCli(c)
if err != nil {
@@ -701,9 +702,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
Sysctl: sysctl,
}
- if err := secConfig.SetLabelOpts(runtime, pid, ipc); err != nil {
- return nil, err
- }
if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil {
return nil, err
}
diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go
index ee212234f..e76750042 100644
--- a/cmd/podman/shared/intermediate.go
+++ b/cmd/podman/shared/intermediate.go
@@ -425,6 +425,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes
m["memory-swappiness"] = newCRInt64(c, "memory-swappiness")
m["name"] = newCRString(c, "name")
m["network"] = newCRString(c, "network")
+ m["no-healthcheck"] = newCRBool(c, "no-healthcheck")
m["no-hosts"] = newCRBool(c, "no-hosts")
m["oom-kill-disable"] = newCRBool(c, "oom-kill-disable")
m["oom-score-adj"] = newCRInt(c, "oom-score-adj")
diff --git a/cni/87-podman-bridge.conflist b/cni/87-podman-bridge.conflist
index a7bcf47bb..13b09a5b5 100644
--- a/cni/87-podman-bridge.conflist
+++ b/cni/87-podman-bridge.conflist
@@ -1,41 +1,36 @@
{
- "cniVersion": "0.4.0",
- "name": "podman",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman0",
- "isGateway": true,
- "ipMasq": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.88.0.0/16",
- "gateway": "10.88.0.1"
- }
- ]
- ]
+ "cniVersion": "0.4.0",
+ "name": "podman",
+ "plugins": [
+ {
+ "type": "bridge",
+ "bridge": "cni-podman0",
+ "isGateway": true,
+ "ipMasq": true,
+ "ipam": {
+ "type": "host-local",
+ "routes": [{ "dst": "0.0.0.0/0" }],
+ "ranges": [
+ [
+ {
+ "subnet": "10.88.0.0/16",
+ "gateway": "10.88.0.1"
}
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": "iptables"
- },
- {
- "type": "tuning"
- }
- ]
+ ]
+ ]
+ }
+ },
+ {
+ "type": "portmap",
+ "capabilities": {
+ "portMappings": true
+ }
+ },
+ {
+ "type": "firewall"
+ },
+ {
+ "type": "tuning"
+ }
+ ]
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 10d40a0c9..13be64e06 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1888,6 +1888,11 @@ _podman_container_run() {
--expose
--gidmap
--group-add
+ --health-cmd
+ --health-interval
+ --health-retries
+ --health-start-period
+ --health-timeout
--hostname -h
--http-proxy
--image-volume
@@ -1906,6 +1911,7 @@ _podman_container_run() {
--memory-reservation
--name
--network
+ --no-healthcheck
--no-hosts
--oom-score-adj
--pid
@@ -2897,13 +2903,21 @@ _podman_image_exists() {
_podman_pod_create() {
local options_with_args="
+ --add-host
--cgroup-parent
+ --dns
+ --dns-opt
+ --dns-search
--infra-command
--infra-image
+ --ip
--label-file
--label
-l
+ --mac-address
--name
+ --network
+ --no-hosts
--podidfile
--publish
-p
diff --git a/contrib/build_rpm.sh b/contrib/build_rpm.sh
index b162a9c88..de6941199 100755
--- a/contrib/build_rpm.sh
+++ b/contrib/build_rpm.sh
@@ -46,10 +46,15 @@ if [[ $pkg_manager == *dnf ]]; then
)
fi
-# btrfs-progs-devel is not available in CentOS/RHEL-8
-if ! (grep -i 'Red Hat\|CentOS' /etc/redhat-release | grep " 8" ); then
+# Package name on fedora 30 is golang-github-cpuguy83-go-md2man
+if (grep -i 'Fedora' /etc/redhat-release | grep " 30" ) ; then
PKGS+=(golang-github-cpuguy83-go-md2man \
btrfs-progs-devel \
+ )
+# btrfs-progs-devel is not available in CentOS/RHEL-8
+elif ! (grep -i 'Red Hat\|CentOS' /etc/redhat-release | grep " 8" ) ; then
+ PKGS+=(golang-github-cpuguy83-md2man \
+ btrfs-progs-devel \
)
fi
diff --git a/contrib/cirrus/README.md b/contrib/cirrus/README.md
index 49f713a8f..3789965d6 100644
--- a/contrib/cirrus/README.md
+++ b/contrib/cirrus/README.md
@@ -216,10 +216,10 @@ the ``cache_images`` Task) some input parameters are required:
to limit the base-images produced. For example,
``PACKER_BUILDS=fedora,image-builder-image``.
-If there is an existing 'image-builder-image' within GCE, it may be utilized
-to produce base-images (in addition to cache-images). However it must be
-created with support for nested-virtualization, and with elevated cloud
-privileges (to access GCE, from within the GCE VM). For example:
+If there is no existing 'image-builder-image' within GCE, a new
+one may be bootstrapped by creating a CentOS 7 VM with support for
+nested-virtualization, and with elevated cloud privileges (to access
+GCE, from within the GCE VM). For example:
```
$ alias pgcloud='sudo podman run -it --rm -e AS_ID=$UID
@@ -229,34 +229,33 @@ $ URL=https://www.googleapis.com/auth
$ SCOPES=$URL/userinfo.email,$URL/compute,$URL/devstorage.full_control
# The --min-cpu-platform is critical for nested-virt.
-$ pgcloud compute instances create $USER-making-images \
- --image-family image-builder-image \
+$ pgcloud compute instances create $USER-image-builder \
+ --image-family centos-7 \
--boot-disk-size "200GB" \
--min-cpu-platform "Intel Haswell" \
--machine-type n1-standard-2 \
--scopes $SCOPES
```
-Alternatively, if there is no image-builder-image available yet, a bare-metal
-CentOS 7 machine with network access to GCE is required. Software dependencies
-can be obtained from the ``packer/image-builder-image_base_setup.sh`` script.
+Then from that VM, execute the
+``contrib/cirrus/packer/image-builder-image_base_setup.sh`` script.
+Shutdown the VM, and convert it into a new image-builder-image.
-In both cases, the following can be used to setup and build base-images.
+Building new base images is done by first creating a VM from an
+image-builder-image and copying the credentials json file to it.
```
-$ IP_ADDRESS=1.2.3.4 # EXTERNAL_IP from command output above
-$ rsync -av $PWD centos@$IP_ADDRESS:.
-$ scp $GOOGLE_APPLICATION_CREDENTIALS centos@$IP_ADDRESS:.
-$ ssh centos@$IP_ADDRESS
-...
+$ hack/get_ci_vm.sh image-builder-image-1541772081
+...in another terminal...
+$ pgcloud compute scp /path/to/gac.json $USER-image-builder-image-1541772081:.
```
-When ready, change to the ``packer`` sub-directory, and build the images:
+Then, on the VM, change to the ``packer`` sub-directory, and build the images:
```
$ cd libpod/contrib/cirrus/packer
$ make libpod_base_images GCP_PROJECT_ID=<VALUE> \
- GOOGLE_APPLICATION_CREDENTIALS=<VALUE> \
+ GOOGLE_APPLICATION_CREDENTIALS=/path/to/gac.json \
PACKER_BUILDS=<OPTIONAL>
```
@@ -283,7 +282,5 @@ values follows:
* `rootless`: Causes a random, ordinary user account to be created
and utilized for testing.
* `in_podman`: Causes testing to occur within a container executed by
- Podman on the host.
-* `cgroupv2`: The kernel on this VM was prepared with options to enable v2 cgroups
* `windows`: See **darwin**
* `darwin`: Signals the ``special_testing_cross`` task to cross-compile the remote client.
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index e8f6c50d9..d5e6ec884 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -16,6 +16,16 @@ fi
cd "$GOSRC"
+# Transition workaround: runc is still the default for upstream development
+handle_crun() {
+ # For systems with crun installed, assume CgroupsV2 and use it
+ if type -P crun &> /dev/null
+ then
+ warn "Replacing runc -> crun in libpod.conf"
+ sed -i -r -e 's/^runtime = "runc"/runtime = "crun"/' /usr/share/containers/libpod.conf
+ fi
+}
+
case "$SPECIALMODE" in
in_podman)
${CONTAINER_RUNTIME} run --rm --privileged --net=host \
@@ -36,27 +46,24 @@ case "$SPECIALMODE" in
-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
-o CheckHostIP=no $GOSRC/$SCRIPT_BASE/rootless_test.sh ${TESTSUITE}
;;
- cgroupv2)
- setenforce 0
- dnf install -y crun
- export OCI_RUNTIME=/usr/bin/crun
- make
- make install PREFIX=/usr ETCDIR=/etc
- make install.config PREFIX=/usr
- make test-binaries
- make local${TESTSUITE}
- ;;
endpoint)
make
make install PREFIX=/usr ETCDIR=/etc
+ #handle_crun
make test-binaries
make endpoint
;;
+ bindings)
+ make
+ make install PREFIX=/usr ETCDIR=/etc
+ cd pkg/bindings/test && ginkgo -r
+ ;;
none)
make
make install PREFIX=/usr ETCDIR=/etc
make install.config PREFIX=/usr
make test-binaries
+ handle_crun
if [[ "$TEST_REMOTE_CLIENT" == "true" ]]
then
make remote${TESTSUITE} VARLINK_LOG=$VARLINK_LOG
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index 1e237085f..71ad67c74 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -7,10 +7,10 @@
source /etc/environment # not always loaded under all circumstances
# Under some contexts these values are not set, make sure they are.
-USER="$(whoami)"
-HOME="$(getent passwd $USER | cut -d : -f 6)"
-[[ -n "$UID" ]] || UID=$(getent passwd $USER | cut -d : -f 3)
-GID=$(getent passwd $USER | cut -d : -f 4)
+export USER="$(whoami)"
+export HOME="$(getent passwd $USER | cut -d : -f 6)"
+[[ -n "$UID" ]] || export UID=$(getent passwd $USER | cut -d : -f 3)
+export GID=$(getent passwd $USER | cut -d : -f 4)
# Essential default paths, many are overridden when executing under Cirrus-CI
export GOPATH="${GOPATH:-/var/tmp/go}"
@@ -59,13 +59,13 @@ PACKER_VER="1.4.2"
# CSV of cache-image names to build (see $PACKER_BASE/libpod_images.json)
# Base-images rarely change, define them here so they're out of the way.
-export PACKER_BUILDS="${PACKER_BUILDS:-ubuntu-18,ubuntu-19,fedora-30,xfedora-30,fedora-29}"
-# Google-maintained base-image names
+export PACKER_BUILDS="${PACKER_BUILDS:-ubuntu-18,ubuntu-19,fedora-31,fedora-30}"
+# Manually produced base-image names (see $SCRIPT_BASE/README.md)
export UBUNTU_BASE_IMAGE="ubuntu-1904-disco-v20190724"
export PRIOR_UBUNTU_BASE_IMAGE="ubuntu-1804-bionic-v20190722a"
# Manually produced base-image names (see $SCRIPT_BASE/README.md)
-export FEDORA_BASE_IMAGE="fedora-cloud-base-30-1-2-1578586410"
-export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-29-1-2-1541789245"
+export FEDORA_BASE_IMAGE="fedora-cloud-base-31-1-9-1578586410"
+export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-30-1-2-1578586410"
export BUILT_IMAGE_SUFFIX="${BUILT_IMAGE_SUFFIX:--$CIRRUS_REPO_NAME-${CIRRUS_BUILD_ID}}"
# IN_PODMAN container image
IN_PODMAN_IMAGE="quay.io/libpod/in_podman:latest"
@@ -79,8 +79,8 @@ SUDOAPTADD="ooe.sh sudo -E add-apt-repository --yes"
# Regex that finds enabled periodic apt configuration items
PERIODIC_APT_RE='^(APT::Periodic::.+")1"\;'
# Short-cuts for retrying/timeout calls
-LILTO="timeout_attempt_delay_command 24s 5 30s"
-BIGTO="timeout_attempt_delay_command 300s 5 30s"
+LILTO="timeout_attempt_delay_command 120s 5 30s"
+BIGTO="timeout_attempt_delay_command 300s 5 60s"
# Safe env. vars. to transfer from root -> $ROOTLESS_USER (go env handled separately)
ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(TEST_REMOTE.*)'
@@ -178,8 +178,7 @@ die() {
}
warn() {
- echo ">>>>> ${2:-WARNING (but no message given!) in ${FUNCNAME[1]}()}" > /dev/stderr
- echo ${1:-1} > /dev/stdout
+ echo ">>>>> ${1:-WARNING (but no message given!) in ${FUNCNAME[1]}()}" > /dev/stderr
}
bad_os_id_ver() {
@@ -456,7 +455,6 @@ _finalize() {
echo "Could not find any files in $CUSTOM_CLOUD_CONFIG_DEFAULTS"
fi
echo "Re-initializing so next boot does 'first-boot' setup again."
- sudo history -c
cd /
sudo rm -rf /var/lib/cloud/instanc*
sudo rm -rf /root/.ssh/*
diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh
index 17f5eb099..34b88e6ea 100755
--- a/contrib/cirrus/logcollector.sh
+++ b/contrib/cirrus/logcollector.sh
@@ -32,6 +32,7 @@ case $1 in
df) showrun df -lhTx tmpfs ;;
ginkgo) showrun cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log ;;
journal) showrun journalctl -b ;;
+ podman) showrun podman system info ;;
varlink)
if [[ "$TEST_REMOTE_CLIENT" == "true" ]]
then
@@ -55,6 +56,7 @@ case $1 in
)
case $OS_RELEASE_ID in
fedora*)
+ cat /etc/fedora-release
PKG_LST_CMD='rpm -q --qf=%{N}-%{V}-%{R}-%{ARCH}\n'
PKG_NAMES+=(\
container-selinux \
@@ -63,6 +65,7 @@ case $1 in
)
;;
ubuntu*)
+ cat /etc/issue
PKG_LST_CMD='dpkg-query --show --showformat=${Package}-${Version}-${Architecture}\n'
PKG_NAMES+=(\
cri-o-runc \
@@ -70,6 +73,8 @@ case $1 in
;;
*) bad_os_id_ver ;;
esac
+ echo "Kernel: " $(uname -r)
+ echo "Cgroups: " $(stat -f -c %T /sys/fs/cgroup)
# Any not-present packages will be listed as such
$PKG_LST_CMD ${PKG_NAMES[@]} | sort -u
;;
diff --git a/contrib/cirrus/packer/Makefile b/contrib/cirrus/packer/Makefile
index fa87d7019..a911cafdb 100644
--- a/contrib/cirrus/packer/Makefile
+++ b/contrib/cirrus/packer/Makefile
@@ -1,9 +1,4 @@
-
-# N/B: PACKER_BUILDS variable is required. Should contain CSV of
-# builder name(s) from applicable YAML file,
-# e.g for names see libpod_images.yml
-
-PACKER_VER ?= 1.4.2
+PACKER_VER ?= 1.4.3
GOARCH=$(shell go env GOARCH)
ARCH=$(uname -m)
PACKER_DIST_FILENAME := packer_${PACKER_VER}_linux_${GOARCH}.zip
@@ -56,8 +51,9 @@ test: libpod_base_images.json libpod_images.json packer
.PHONY: libpod_images
libpod_images: guard-PACKER_BUILDS libpod_images.json packer
- ./packer build -only=${PACKER_BUILDS} \
+ ./packer build \
-force \
+ $(shell test -z "${PACKER_BUILDS}" || echo "-only=${PACKER_BUILDS}") \
-var GOSRC=$(GOSRC) \
-var PACKER_BASE=$(PACKER_BASE) \
-var SCRIPT_BASE=$(SCRIPT_BASE) \
@@ -82,6 +78,7 @@ cidata.iso: user-data meta-data
.PHONY: libpod_base_images
libpod_base_images: guard-GCP_PROJECT_ID guard-GOOGLE_APPLICATION_CREDENTIALS libpod_base_images.json cidata.iso cidata.ssh packer
PACKER_CACHE_DIR=/tmp ./packer build \
+ $(shell test -z "${PACKER_BUILDS}" || echo "-only=${PACKER_BUILDS}") \
-force \
-var TIMESTAMP=$(TIMESTAMP) \
-var TTYDEV=$(TTYDEV) \
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh
index 6cfaa05ce..591a59a05 100644
--- a/contrib/cirrus/packer/fedora_setup.sh
+++ b/contrib/cirrus/packer/fedora_setup.sh
@@ -15,100 +15,106 @@ install_ooe
export GOPATH="$(mktemp -d)"
trap "sudo rm -rf $GOPATH" EXIT
-ooe.sh sudo dnf update -y
+$BIGTO ooe.sh sudo dnf update -y
echo "Enabling updates-testing repository"
-ooe.sh sudo dnf install -y 'dnf-command(config-manager)'
-ooe.sh sudo dnf config-manager --set-enabled updates-testing
+$LILTO ooe.sh sudo dnf install -y 'dnf-command(config-manager)'
+$LILTO ooe.sh sudo dnf config-manager --set-enabled updates-testing
-echo "Installing general build/test dependencies"
-ooe.sh sudo dnf install -y \
- atomic-registries \
- autoconf \
- automake \
- bash-completion \
- bats \
- bridge-utils \
- btrfs-progs-devel \
- bzip2 \
- conmon \
- container-selinux \
- containernetworking-plugins \
- containers-common \
- criu \
- device-mapper-devel \
- emacs-nox \
- file \
- findutils \
- fuse3 \
- fuse3-devel \
- gcc \
- git \
- glib2-devel \
- glibc-static \
- gnupg \
- go-md2man \
- golang \
- golang-github-cpuguy83-go-md2man \
- gpgme-devel \
- iproute \
- iptables \
- jq \
- libassuan-devel \
- libcap-devel \
- libmsi1 \
- libnet \
- libnet-devel \
- libnl3-devel \
- libseccomp \
- libseccomp-devel \
- libselinux-devel \
- libtool \
- libvarlink-util \
- lsof \
- make \
- msitools \
- nmap-ncat \
- pandoc \
- podman \
- procps-ng \
- protobuf \
- protobuf-c \
- protobuf-c-devel \
- protobuf-compiler \
- protobuf-devel \
- protobuf-python \
- python \
- python2-future \
- python3-dateutil \
- python3-psutil \
- python3-pytoml \
- runc \
- selinux-policy-devel \
- slirp4netns \
- unzip \
- vim \
- which \
- xz \
+echo "Installing general build/test dependencies for Fedora '$OS_RELEASE_VER'"
+REMOVE_PACKAGES=()
+INSTALL_PACKAGES=(\
+ autoconf
+ automake
+ bash-completion
+ bats
+ bridge-utils
+ btrfs-progs-devel
+ bzip2
+ conmon
+ container-selinux
+ containernetworking-plugins
+ containers-common
+ criu
+ device-mapper-devel
+ dnsmasq
+ emacs-nox
+ file
+ findutils
+ fuse3
+ fuse3-devel
+ gcc
+ git
+ glib2-devel
+ glibc-static
+ gnupg
+ go-md2man
+ golang
+ gpgme-devel
+ iproute
+ iptables
+ jq
+ libassuan-devel
+ libcap-devel
+ libmsi1
+ libnet
+ libnet-devel
+ libnl3-devel
+ libseccomp
+ libseccomp-devel
+ libselinux-devel
+ libtool
+ libvarlink-util
+ lsof
+ make
+ msitools
+ nmap-ncat
+ pandoc
+ podman
+ procps-ng
+ protobuf
+ protobuf-c
+ protobuf-c-devel
+ protobuf-devel
+ protobuf-python
+ python
+ python3-dateutil
+ python3-psutil
+ python3-pytoml
+ selinux-policy-devel
+ skopeo
+ slirp4netns
+ unzip
+ vim
+ which
+ xz
zip
+)
+case "$OS_RELEASE_VER" in
+ 30)
+ INSTALL_PACKAGES+=(\
+ atomic-registries
+ golang-github-cpuguy83-go-md2man
+ python2-future
+ runc
+ )
+ ;;
+ 31)
+ INSTALL_PACKAGES+=(crun)
+ REMOVE_PACKAGES+=(runc)
+ ;;
+ *)
+ bad_os_id_ver ;;
+esac
+$BIGTO ooe.sh sudo dnf install -y ${INSTALL_PACKAGES[@]}
+[[ "${#REMOVE_PACKAGES[@]}" -eq "0" ]] || \
+ $LILTO ooe.sh sudo dnf erase -y ${REMOVE_PACKAGES[@]}
# Ensure there are no disruptive periodic services enabled by default in image
systemd_banish
-sudo /tmp/libpod/hack/install_catatonit.sh
-
-# Same script is used for several related contexts
-case "$PACKER_BUILDER_NAME" in
- xfedora*)
- echo "Configuring CGroups v2 enabled on next boot"
- sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"
- sudo dnf install -y crun
- ;& # continue to next matching item
- *)
- echo "Finalizing $PACKER_BUILDER_NAME VM image"
- ;;
-esac
+ooe.sh sudo /tmp/libpod/hack/install_catatonit.sh
rh_finalize
diff --git a/contrib/cirrus/packer/image-builder-image_base-setup.sh b/contrib/cirrus/packer/image-builder-image_base-setup.sh
index 43cfa7180..78772da09 100644
--- a/contrib/cirrus/packer/image-builder-image_base-setup.sh
+++ b/contrib/cirrus/packer/image-builder-image_base-setup.sh
@@ -31,10 +31,8 @@ ooe.sh sudo yum -y install \
libvirt-client \
libvirt-daemon \
make \
- python34 \
- python34 \
- python34-PyYAML \
- python34-PyYAML \
+ python36 \
+ python36-PyYAML \
qemu-img \
qemu-kvm \
qemu-kvm-tools \
diff --git a/contrib/cirrus/packer/libpod_base_images.yml b/contrib/cirrus/packer/libpod_base_images.yml
index bcca440ae..21f3795f1 100644
--- a/contrib/cirrus/packer/libpod_base_images.yml
+++ b/contrib/cirrus/packer/libpod_base_images.yml
@@ -17,14 +17,14 @@ variables:
PRIOR_UBUNTU_BASE_IMAGE:
# Latest Fedora release
- FEDORA_IMAGE_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2"
- FEDORA_CSUM_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-30-1.2-x86_64-CHECKSUM"
- FEDORA_BASE_IMAGE_NAME: 'fedora-cloud-base-30-1-2'
+ FEDORA_IMAGE_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2"
+ FEDORA_CSUM_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/31/Cloud/x86_64/images/Fedora-Cloud-31-1.9-x86_64-CHECKSUM"
+ FEDORA_BASE_IMAGE_NAME: 'fedora-cloud-base-31-1-9'
# Prior Fedora release
- PRIOR_FEDORA_IMAGE_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-Base-29-1.2.x86_64.qcow2"
- PRIOR_FEDORA_CSUM_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/29/Cloud/x86_64/images/Fedora-Cloud-29-1.2-x86_64-CHECKSUM"
- PRIOR_FEDORA_BASE_IMAGE_NAME: 'fedora-cloud-base-29-1-2' # Name to use in GCE
+ PRIOR_FEDORA_IMAGE_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2"
+ PRIOR_FEDORA_CSUM_URL: "https://dl.fedoraproject.org/pub/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-30-1.2-x86_64-CHECKSUM"
+ PRIOR_FEDORA_BASE_IMAGE_NAME: 'fedora-cloud-base-30-1-2'
# The name of the image in GCE used for packer build libpod_images.yml
IBI_BASE_NAME: 'image-builder-image'
diff --git a/contrib/cirrus/packer/libpod_images.yml b/contrib/cirrus/packer/libpod_images.yml
index 01a65d867..074a813af 100644
--- a/contrib/cirrus/packer/libpod_images.yml
+++ b/contrib/cirrus/packer/libpod_images.yml
@@ -51,17 +51,12 @@ builders:
source_image_family: 'prior-ubuntu-base'
- <<: *gce_hosted_image
- name: 'fedora-30'
- source_image: '{{user `FEDORA_BASE_IMAGE`}}'
- source_image_family: 'fedora-base'
-
- - <<: *gce_hosted_image
- name: 'xfedora-30'
+ name: 'fedora-31'
source_image: '{{user `FEDORA_BASE_IMAGE`}}'
source_image_family: 'fedora-base'
- <<: *gce_hosted_image
- name: 'fedora-29'
+ name: 'fedora-30'
source_image: '{{user `PRIOR_FEDORA_BASE_IMAGE`}}'
source_image_family: 'prior-fedora-base'
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index 118ee062a..7c39a76f8 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -59,6 +59,8 @@ $BIGTO $SUDOAPTGET install \
cri-o-runc \
criu \
curl \
+ conmon \
+ dnsmasq \
e2fslibs-dev \
emacs-nox \
file \
@@ -129,7 +131,7 @@ then
ooe.sh sudo update-grub
fi
-sudo /tmp/libpod/hack/install_catatonit.sh
+ooe.sh sudo /tmp/libpod/hack/install_catatonit.sh
ooe.sh sudo make -C /tmp/libpod install.libseccomp.sudo
ubuntu_finalize
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index df510deef..5364dd510 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -47,6 +47,30 @@ case "${OS_RELEASE_ID}" in
setsebool container_manage_cgroup true
if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then
bash "$SCRIPT_BASE/add_second_partition.sh"; fi
+
+ if [[ "$OS_RELEASE_VER" == "31" ]]; then
+ warn "Switching io schedular to deadline to avoid RHBZ 1767539"
+ warn "aka https://bugzilla.kernel.org/show_bug.cgi?id=205447"
+ echo "mq-deadline" > /sys/block/sda/queue/scheduler
+ cat /sys/block/sda/queue/scheduler
+
+ warn "Forcing systemd cgroup manager"
+ X=$(echo "export CGROUP_MANAGER=systemd" | \
+ tee -a /etc/environment) && eval "$X" && echo "$X"
+
+ warn "Testing with crun instead of runc"
+ X=$(echo "export OCI_RUNTIME=/usr/bin/crun" | \
+ tee -a /etc/environment) && eval "$X" && echo "$X"
+
+ warn "Upgrading to the latest crun"
+ # Normally not something to do for stable testing
+ # but crun is new, and late-breaking fixes may be required
+ # on short notice
+ dnf update -y crun
+
+ #warn "Setting SELinux into Permissive mode"
+ #setenforce 0
+ fi
;;
centos) # Current VM is an image-builder-image no local podman/testing
echo "No further setup required for VM image building"
@@ -62,9 +86,6 @@ source "$SCRIPT_BASE/lib.sh"
make install.tools
case "$SPECIALMODE" in
- cgroupv2)
- remove_packaged_podman_files # we're building from source
- ;;
none)
[[ -n "$CROSS_PLATFORM" ]] || \
remove_packaged_podman_files
@@ -72,6 +93,9 @@ case "$SPECIALMODE" in
endpoint)
remove_packaged_podman_files
;;
+ bindings)
+ remove_packaged_podman_files
+ ;;
rootless)
# Only do this once, even if ROOTLESS_USER (somehow) changes
if ! grep -q 'ROOTLESS_USER' /etc/environment
diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh
index c6c77d17e..2852c31ae 100755
--- a/contrib/cirrus/unit_test.sh
+++ b/contrib/cirrus/unit_test.sh
@@ -12,6 +12,7 @@ make localunit
case "$SPECIALMODE" in
in_podman) ;&
+ bindings) ;&
rootless) ;&
none)
make
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 276dd327e..a9c3bc3be 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -43,6 +43,11 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
+%if 0%{?fedora}
+Epoch: 99
+%else
+Epoch: 0
+%endif
Version: 1.8.1
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
diff --git a/docs/source/markdown/libpod.conf.5.md b/docs/source/markdown/libpod.conf.5.md
index c28c80b56..ca45bccf6 100644
--- a/docs/source/markdown/libpod.conf.5.md
+++ b/docs/source/markdown/libpod.conf.5.md
@@ -83,7 +83,8 @@ libpod to manage containers.
containers and pods are visible.
**label**="true|false"
- Indicates whether the containers should use label separation.
+ Indicates whether the containers should use label separation by default.
+ Can be overridden via `--security-opt label=...` on the CLI.
**num_locks**=""
Number of locks available for containers and pods. Each created container or pod consumes one lock.
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 738644c16..12f099e65 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -172,13 +172,20 @@ The [username[:password]] to use to authenticate with the registry if required.
If one or both values are not supplied, a command line prompt will appear and the
value can be entered. The password is entered without echo.
-**--device**=*device*
+**--device**=_host-device_[**:**_container-device_][**:**_permissions_]
-Add a host device to the container. The format is `<device-on-host>[:<device-on-container>][:<permissions>]` (e.g. --device=/dev/sdc:/dev/xvdc:rwm)
+Add a host device to the container. Optional *permissions* parameter
+can be used to specify device permissions, it is combination of
+**r** for read, **w** for write, and **m** for **mknod**(2).
-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`.
+Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
+
+Note: if _host_device_ is a symbolic link then it will be resolved first.
+The container will only store the major and minor numbers of the host device.
+
+Note: if the user only has access rights via a group, accessing the device
+from inside a rootless container will fail. The **crun**(1) runtime offers a
+workaround for this by adding the option **--annotation run.oci.keep_original_groups=1**.
**--disable-compression, -D**
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index ca38be6a1..3c5f81764 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -201,13 +201,20 @@ it in the **libpod.conf** file: see **libpod.conf(5)** for more information.
Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*.
-**--device**=*device*
+**--device**=_host-device_[**:**_container-device_][**:**_permissions_]
-Add a host device to the container. The format is `<device-on-host>[:<device-on-container>][:<permissions>]` (e.g. --device=/dev/sdc:/dev/xvdc:rwm)
+Add a host device to the container. Optional *permissions* parameter
+can be used to specify device permissions, it is combination of
+**r** for read, **w** for write, and **m** for **mknod**(2).
-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`.
+Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
+
+Note: if _host_device_ is a symbolic link then it will be resolved first.
+The container will only store the major and minor numbers of the host device.
+
+Note: if the user only has access rights via a group, accessing the device
+from inside a rootless container will fail. The **crun**(1) runtime offers a
+workaround for this by adding the option **--annotation run.oci.keep_original_groups=1**.
**--device-cgroup-rule**="type major:minor mode"
@@ -557,6 +564,10 @@ Valid values are:
Not implemented
+**--no-healthcheck**=*true|false*
+
+Disable any defined healthchecks for container.
+
**--no-hosts**=*true|false*
Do not create /etc/hosts for the container.
diff --git a/docs/source/markdown/podman-images.1.md b/docs/source/markdown/podman-images.1.md
index d22fb940f..09778e3c2 100644
--- a/docs/source/markdown/podman-images.1.md
+++ b/docs/source/markdown/podman-images.1.md
@@ -29,11 +29,11 @@ Filter output based on conditions provided
Filters:
- **after==TIMESTRING**
- Filter on images created after the given time.Time.
+ **since=IMAGE**
+ Filter on images created after the given IMAGE (name or tag).
- **before==TIMESTRING**
- Filter on images created before the given time.Time.
+ **before=IMAGE**
+ Filter on images created before the given IMAGE (name or tag).
**dangling=true|false**
Show dangling images. Dangling images are a file system layer that was used in a previous build of an image and is no longer referenced by any active images. They are denoted with the <none> tag, consume disk space and serve no active purpose.
diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md
index 8a84d359d..a69b311eb 100644
--- a/docs/source/markdown/podman-login.1.md
+++ b/docs/source/markdown/podman-login.1.md
@@ -4,11 +4,12 @@
podman\-login - Login to a container registry
## SYNOPSIS
-**podman login** [*options*] *registry*
+**podman login** [*options*] [*registry*]
## DESCRIPTION
**podman login** logs into a specified registry server with the correct username
-and password. **podman login** reads in the username and password from STDIN.
+and password. If the registry is not specified, the first registry under [registries.search]
+from registries.conf will be used. **podman login** reads in the username and password from STDIN.
The username and password can also be set using the **username** and **password** flags.
The path of the authentication file can be specified by the user by setting the **authfile**
flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**.
@@ -17,7 +18,7 @@ flag. The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**.
**podman login [GLOBAL OPTIONS]**
-**podman login [OPTIONS] REGISTRY [GLOBAL OPTIONS]**
+**podman login [OPTIONS] [REGISTRY] [GLOBAL OPTIONS]**
## OPTIONS
diff --git a/docs/source/markdown/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md
index 01dc52ecd..8b9f75760 100644
--- a/docs/source/markdown/podman-logout.1.md
+++ b/docs/source/markdown/podman-logout.1.md
@@ -8,7 +8,8 @@ podman\-logout - Logout of a container registry
## DESCRIPTION
**podman logout** logs out of a specified registry server by deleting the cached credentials
-stored in the **auth.json** file. The path of the authentication file can be overridden by the user by setting the **authfile** flag.
+stored in the **auth.json** file. If the registry is not specified, the first registry under [registries.search]
+from registries.conf will be used. The path of the authentication file can be overridden by the user by setting the **authfile** flag.
The default path used is **${XDG\_RUNTIME\_DIR}/containers/auth.json**.
All the cached credentials can be removed by setting the **all** flag.
diff --git a/docs/source/markdown/podman-logs.1.md b/docs/source/markdown/podman-logs.1.md
index 5507ba13a..66308c2b5 100644
--- a/docs/source/markdown/podman-logs.1.md
+++ b/docs/source/markdown/podman-logs.1.md
@@ -11,7 +11,7 @@ podman\-logs - Display the logs of one or more containers
## DESCRIPTION
The podman logs command batch-retrieves whatever logs are present for one or more containers at the time of execution.
This does not guarantee execution order when combined with podman run (i.e. your run may not have generated
-any logs at the time you execute podman logs
+any logs at the time you execute podman logs).
## OPTIONS
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index cd1de6401..dba31f681 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -15,50 +15,82 @@ containers added to it. The pod id is printed to STDOUT. You can then use
## OPTIONS
+**--add-host**=_host_:_ip_
+
+Add a host to the /etc/hosts file shared between all containers in the pod.
+
**--cgroup-parent**=*path*
Path to cgroups under which the cgroup for the pod will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
+**--dns**=*ipaddr*
+
+Set custom DNS servers in the /etc/resolv.conf file that will be shared between all containers in the pod. A special option, "none" is allowed which disables creation of /etc/resolv.conf for the pod.
+
+**--dns-opt**=*option*
+
+Set custom DNS options in the /etc/resolv.conf file that will be shared between all containers in the pod.
+
+**--dns-search**=*domain*
+
+Set custom DNS search domains in the /etc/resolv.conf file that will be shared between all containers in the pod.
+
**--help**
-Print usage statement
+Print usage statement.
-**--infra**
+**--infra**=**true**|**false**
-Create an infra container and associate it with the pod. An infra container is a lightweight container used to coordinate the shared kernel namespace of a pod. Default: true
+Create an infra container and associate it with the pod. An infra container is a lightweight container used to coordinate the shared kernel namespace of a pod. Default: true.
**--infra-command**=*command*
-The command that will be run to start the infra container. Default: "/pause"
+The command that will be run to start the infra container. Default: "/pause".
**--infra-image**=*image*
-The image that will be created for the infra container. Default: "k8s.gcr.io/pause:3.1"
+The image that will be created for the infra container. Default: "k8s.gcr.io/pause:3.1".
+
+**--ip**=*ipaddr*
+
+Set a static IP for the pod's shared network.
**-l**, **--label**=*label*
-Add metadata to a pod (e.g., --label com.example.key=value)
+Add metadata to a pod (e.g., --label com.example.key=value).
**--label-file**=*label*
-Read in a line delimited file of labels
+Read in a line delimited file of labels.
+
+**--mac-address**=*address*
+
+Set a static MAC address for the pod's shared network.
**-n**, **--name**=*name*
-Assign a name to the pod
+Assign a name to the pod.
+
+**--network**=*mode*
+
+Set network mode for the pod. Supported values are *bridge* (the default), *host* (do not create a network namespace, all containers in the pod will use the host's network), or a comma-separated list of the names of CNI networks the pod should join.
+
+**--no-hosts**=**true**|**false**
+
+Disable creation of /etc/hosts for the pod.
**--podidfile**=*podid*
-Write the pod ID to the file
+Write the pod ID to the file.
**-p**, **--publish**=*port*
-Publish a port or range of ports from the pod to the host
+Publish a port or range of ports from the pod to the host.
Format: `ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort`
Both hostPort and containerPort can be specified as a range of ports.
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range.
-Use `podman port` to see the actual mapping: `podman port CONTAINER $CONTAINERPORT`
+Use `podman port` to see the actual mapping: `podman port CONTAINER $CONTAINERPORT`.
NOTE: This cannot be modified once the pod is created.
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index 23bf9f45d..2f8112aab 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -55,7 +55,8 @@ Valid placeholders for the Go template are listed below:
| **Placeholder** | **Description** |
| --------------- | ------------------------------------------------ |
| .ID | Container ID |
-| .Image | Image ID/Name |
+| .Image | Image Name/ID |
+| .ImageID | Image ID |
| .Command | Quoted command used |
| .CreatedAt | Creation time for container |
| .RunningFor | Time elapsed since container was started |
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index f391307b3..220b32a46 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -218,6 +218,9 @@ can be used to specify device permissions, it is combination of
Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
+Note: if _host_device_ is a symbolic link then it will be resolved first.
+The container will only store the major and minor numbers of the host device.
+
Note: if the user only has access rights via a group, accessing the device
from inside a rootless container will fail. The **crun**(1) runtime offers a
workaround for this by adding the option **--annotation run.oci.keep_original_groups=1**.
@@ -560,6 +563,10 @@ Valid _mode_ values are:
Not implemented.
+**--no-healthcheck**=*true|false*
+
+Disable any defined healthchecks for container.
+
**--no-hosts**=**true**|**false**
Do not create _/etc/hosts_ for the container.
diff --git a/go.mod b/go.mod
index 34967bdd1..170e9b435 100644
--- a/go.mod
+++ b/go.mod
@@ -4,19 +4,17 @@ go 1.12
require (
github.com/BurntSushi/toml v0.3.1
- github.com/blang/semver v3.5.1+incompatible // indirect
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b
- github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
github.com/containernetworking/plugins v0.8.5
- github.com/containers/buildah v1.13.1
+ github.com/containers/buildah v1.14.1-0.20200227103754-f0c3fd7c3d34
+ github.com/containers/common v0.4.2 // indirect
github.com/containers/conmon v2.0.10+incompatible
github.com/containers/image/v5 v5.2.1
github.com/containers/psgo v1.4.0
- github.com/containers/storage v1.15.8
+ github.com/containers/storage v1.16.0
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
- github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b
github.com/cyphar/filepath-securejoin v0.2.2
github.com/davecgh/go-spew v1.1.1
@@ -25,27 +23,18 @@ require (
github.com/docker/docker-credential-helpers v0.6.3
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.4.0
- github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
- github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 // indirect
- github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect
- github.com/elazarl/goproxy/ext v0.0.0-20190911111923-ecfe977594f1 // indirect
github.com/etcd-io/bbolt v1.3.3
- github.com/fatih/camelcase v1.0.0 // indirect
github.com/fsnotify/fsnotify v1.4.7
github.com/ghodss/yaml v1.0.0
- github.com/go-ini/ini v1.51.1 // indirect
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e
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.4
github.com/gorilla/schema v1.1.0
github.com/hashicorp/go-multierror v1.0.0
github.com/hpcloud/tail v1.0.0
github.com/json-iterator/go v1.1.9
- github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd // indirect
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
- github.com/olekukonko/tablewriter v0.0.4 // indirect
github.com/onsi/ginkgo v1.12.0
github.com/onsi/gomega v1.9.0
github.com/opencontainers/go-digest v1.0.0-rc1
@@ -53,33 +42,27 @@ require (
github.com/opencontainers/runc v1.0.0-rc9
github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7
github.com/opencontainers/runtime-tools v0.9.0
- github.com/opencontainers/selinux v1.3.1
+ github.com/opencontainers/selinux v1.3.2
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.9.1
- github.com/pkg/profile v1.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0
github.com/rootless-containers/rootlesskit v0.8.0
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
github.com/sirupsen/logrus v1.4.2
- github.com/spf13/cobra v0.0.5
+ github.com/spf13/cobra v0.0.6
github.com/spf13/pflag v1.0.5
- github.com/stretchr/testify v1.4.0
+ github.com/stretchr/testify v1.5.1
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/uber/jaeger-client-go v2.22.1+incompatible
- github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 // indirect
+ github.com/uber/jaeger-lib v2.2.0+incompatible // indirect
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b
github.com/vishvananda/netlink v1.1.0
- go.uber.org/atomic v1.4.0 // indirect
- golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
- golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
+ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
golang.org/x/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2
- google.golang.org/appengine v1.6.1 // indirect
- google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 // indirect
gopkg.in/yaml.v2 v2.2.8
gotest.tools/v3 v3.0.2 // indirect
k8s.io/api v0.17.3
k8s.io/apimachinery v0.17.3
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
- k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a // indirect
)
diff --git a/go.sum b/go.sum
index 97a5f1e31..75dc29cfc 100644
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,7 @@ github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhj
github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
@@ -34,6 +35,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
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 h1:7hqmJYuaEK3qwVjWubYiht3j93YI0WQBuysxHIfUriU=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
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=
@@ -41,6 +43,7 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37 h1:uxxtrnACqI9zK4ENDMf0WpXfUsHP5V8liuq5QdgDISU=
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b h1:T4nWG1TXIxeor8mAu5bFguPJgSIGhZqv/f0z55KCrJM=
github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -67,8 +70,22 @@ github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7
github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
github.com/containers/buildah v1.13.1 h1:EdhllQxXmOZ56mGFf68AkrpIj9XtEkkGq0WaPWFuGM0=
github.com/containers/buildah v1.13.1/go.mod h1:U0LcOzSqoYdyQC5L2hMeLbtCDuCCLxmZV1eb+SWY4GA=
+github.com/containers/buildah v1.14.1-0.20200219125159-7cd6f7d04842 h1:OM/a/RYfWe721ZjDJf4RyGhyvEGJIdmx9tYZl1bq5jY=
+github.com/containers/buildah v1.14.1-0.20200219125159-7cd6f7d04842/go.mod h1:dmPZHakxkaCVu5oefZaLVAZXNGva9PqVSMVK3hkarvA=
+github.com/containers/buildah v1.14.1-0.20200222102502-002dffb8d2cb h1:FvrlxHKZoo8PYpzev0pM8S+lPBj+p7yK4yVgK95uJ1U=
+github.com/containers/buildah v1.14.1-0.20200222102502-002dffb8d2cb/go.mod h1:tsos+87us4LpjyPwtgXQmDkOj5SYrpsMyRVcDTOQ5aA=
+github.com/containers/buildah v1.14.1-0.20200225113533-39bd7e0a7a73 h1:TyGEOd0O6oigg1WA+bprBTgeHH8815fNgOUYhh1I2Vs=
+github.com/containers/buildah v1.14.1-0.20200225113533-39bd7e0a7a73/go.mod h1:sdMVVcCTvvAj9o9dk/j6EnNJJadjxqjcI4Yy9WoWxSg=
+github.com/containers/buildah v1.14.1-0.20200227103754-f0c3fd7c3d34 h1:SaK9ADT5JdVL29Z8snwl+bqmi1usnNyis+7Hd5+jJjw=
+github.com/containers/buildah v1.14.1-0.20200227103754-f0c3fd7c3d34/go.mod h1:sdMVVcCTvvAj9o9dk/j6EnNJJadjxqjcI4Yy9WoWxSg=
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/common v0.3.0 h1:9ysL/OfPcMls1Ac3jzFA4XZJVSD/JG7Dst3uQSwQtwA=
+github.com/containers/common v0.3.0/go.mod h1:AiPCv0ZcBOVshnup/X6MuaqkySZQZ3iBWfInjJFIl40=
+github.com/containers/common v0.4.1 h1:Uu7f2ZDM/5xsqOkZwIEVKSjUI3YxKjvNIY5x57kjaKo=
+github.com/containers/common v0.4.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
+github.com/containers/common v0.4.2 h1:O5d1gj/xdpQdZi0MEivRQ/7AeRaVeHdbSP/bvShw458=
+github.com/containers/common v0.4.2/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
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.1.0/go.mod h1:BKlMD34WxRo1ruGHHEOrPQP0Qci7SWoPwU6fS7arsCU=
@@ -76,6 +93,7 @@ github.com/containers/image/v5 v5.2.0 h1:DowY5OII5x9Pb6Pt76vnHU79BgG4/jdwhZjeAj2
github.com/containers/image/v5 v5.2.0/go.mod h1:IAub4gDGvXoxaIAdNy4e3FbVTDPVNMv9F0UfVVFbYCU=
github.com/containers/image/v5 v5.2.1 h1:rQR6QSUneWBoW1bTFpP9EJJTevQFv27YsKYQVJIzg+s=
github.com/containers/image/v5 v5.2.1/go.mod h1:TfhmLwH+v1/HBVPIWH7diLs8XwcOkP3c7t7JFgqaUEc=
+github.com/containers/libpod v1.8.0/go.mod h1:53h7AOg4tQSX1rqKfR78/6Us/whERRzCQ20z0GiR44U=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJtUcZgK7sPglscXtxvMOnFOa6wd09VWLM=
@@ -87,6 +105,9 @@ github.com/containers/storage v1.15.3/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I
github.com/containers/storage v1.15.5/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
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/containers/storage v1.16.0 h1:sD+s7BmiNBh61CuHN3j8PXGCwMtV9zPVJETAlshIf3w=
+github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPbNkN/xb0TfG0=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
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.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@@ -100,6 +121,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b h1:SgS+WV10y2Bubuy2HquSBori6DXj9sqRN77Hgs5H7Qc=
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b/go.mod h1:ZOuIEOp/3MB1eCBWANnNxM3zUA3NWh76wSRCsnKAg2c=
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
@@ -113,6 +135,8 @@ 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
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=
@@ -133,6 +157,7 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
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/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
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=
@@ -151,6 +176,10 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/go-dockerclient v1.6.0 h1:f7j+AX94143JL1H3TiqSMkM4EcLDI0De1qD4GGn3Hig=
github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc=
+github.com/fsouza/go-dockerclient v1.6.1 h1:qBvbtwBTpOYktncvxjFMHxJHuGG19lb2fvAFqfXeh7w=
+github.com/fsouza/go-dockerclient v1.6.1/go.mod h1:g2pGMa82+SdtAicFSpxGJc1Anx//HHssXyWLwMRxaqg=
+github.com/fsouza/go-dockerclient v1.6.3 h1:VS/I3mxieZVIeaWXd57JKvSjheELafUJYtblGg75RIQ=
+github.com/fsouza/go-dockerclient v1.6.3/go.mod h1:OiSy/IhZIF+zheikZkXK7LVpGzxWchJPJKGWhBqOK4M=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -186,6 +215,7 @@ github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09Vjb
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
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/groupcache v0.0.0-20190129154638-5b532d6fd5ef/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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -193,10 +223,13 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
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/btree v1.0.0/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/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/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
@@ -217,8 +250,12 @@ 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/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -239,8 +276,11 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/insomniacslk/dhcp v0.0.0-20190712084813-dc1a53400564/go.mod h1:CfMdguCK66I5DAUJgGKyNz8aB6vO5dZzkm9Xep6WGvw=
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111 h1:NAAiV9ass6VReWFjuxqrMIq12WKlSULI6Gs3PxQghLA=
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
+github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 h1:rw3IAne6CDuVFlZbPOkA7bhxlqawFh7RJJ+CejfMaxE=
+github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
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/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -260,6 +300,8 @@ github.com/klauspost/compress v1.8.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.9.4/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/compress v1.10.0 h1:92XGj1AcYzA6UrVdd4qIIBrT8OroryvRvdmg/IfmC7Y=
+github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
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=
@@ -267,9 +309,11 @@ 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=
@@ -283,6 +327,8 @@ github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq
github.com/mattn/go-shellwords v1.0.6/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/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
+github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
@@ -297,6 +343,7 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
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=
@@ -310,6 +357,7 @@ github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgi
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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
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=
@@ -352,6 +400,8 @@ github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOl
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/opencontainers/selinux v1.3.2 h1:DR4lL9SYVjgcTZKEZIncvDU06fKSc/eygjmNGOA3E1s=
+github.com/opencontainers/selinux v1.3.2/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/imagebuilder v1.1.1 h1:KAUR31p8UBJdfVO42azWgb+LeMAed2zaKQ19e0C0X2I=
@@ -376,21 +426,29 @@ github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BU
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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
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=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
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.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
+github.com/rhatdan/buildah v0.0.0-20200218224501-fc6baddc9762 h1:HO8tASQj1anmipujM8qxt3XEmJGQfjc8xW6ksRkZpic=
+github.com/rhatdan/buildah v0.0.0-20200218224501-fc6baddc9762/go.mod h1:dmPZHakxkaCVu5oefZaLVAZXNGva9PqVSMVK3hkarvA=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rootless-containers/rootlesskit v0.7.2 h1:gcWQ9/GN98ne1AqnoeOgQ8e6qpKd3BuB4ug+2h95Fr0=
github.com/rootless-containers/rootlesskit v0.7.2/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA=
@@ -412,11 +470,15 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs=
+github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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=
@@ -424,25 +486,35 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
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/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=
+github.com/stretchr/testify v1.5.0 h1:DMOzIV76tmoDNE9pX6RSN0aDtCYeCg5VueieJaAo1uw=
+github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/u-root/u-root v5.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
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=
github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
+github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=
+github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
@@ -470,15 +542,21 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
+github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66 h1:F6RPtD6im1kY4bmLByRlOLOZwsPP7mw7cxR1v2CotL0=
github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+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=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -490,6 +568,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
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=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -504,12 +584,14 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
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=
@@ -518,6 +600,7 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -531,6 +614,7 @@ golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -560,7 +644,10 @@ 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=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -577,23 +664,29 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04=
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
@@ -601,6 +694,7 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4
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/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=
@@ -609,10 +703,12 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
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.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -652,6 +748,7 @@ 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-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 h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn3b/WPHqD5mBvP4=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a h1:2jUDc9gJja832Ftp+QbDV0tVhQHMISFn01els+2ZAcw=
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
diff --git a/hack/get_ci_vm.sh b/hack/get_ci_vm.sh
index 22f902e2d..768137213 100755
--- a/hack/get_ci_vm.sh
+++ b/hack/get_ci_vm.sh
@@ -97,7 +97,7 @@ keys=[k for k in env if "ENCRYPTED" not in str(env[k])]
for k,v in env.items():
v=str(v)
if "ENCRYPTED" not in v:
- print "{0}=\"{1}\"".format(k, v),
+ print("{0}=\"{1}\"".format(k, v)),
'
}
diff --git a/libpod/common_test.go b/libpod/common_test.go
index 83b162c8a..63ea4f41b 100644
--- a/libpod/common_test.go
+++ b/libpod/common_test.go
@@ -23,7 +23,6 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error)
Name: name,
RootfsImageID: id,
RootfsImageName: "testimg",
- ImageVolumes: true,
StaticDir: "/does/not/exist/",
LogPath: "/does/not/exist/",
Stdin: true,
diff --git a/libpod/config/config.go b/libpod/config/config.go
index 13c128688..c72a0efc7 100644
--- a/libpod/config/config.go
+++ b/libpod/config/config.go
@@ -2,7 +2,7 @@ package config
import (
"bytes"
- "io/ioutil"
+ "fmt"
"os"
"os/exec"
"path/filepath"
@@ -287,18 +287,16 @@ type DBConfig struct {
}
// readConfigFromFile reads the specified config file at `path` and attempts to
-// unmarshal its content into a Config.
-func readConfigFromFile(path string) (*Config, error) {
- var config Config
-
- configBytes, err := ioutil.ReadFile(path)
+// unmarshal its content into a Config. The config param specifies the previous
+// default config. If the path, only specifies a few fields in the Toml file
+// the defaults from the config parameter will be used for all other fields.
+func readConfigFromFile(path string, config *Config) (*Config, error) {
+ logrus.Debugf("Reading configuration file %q", path)
+ _, err := toml.DecodeFile(path, config)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err)
}
- logrus.Debugf("Reading configuration file %q", path)
- err = toml.Unmarshal(configBytes, &config)
-
// For the sake of backwards compat we need to check if the config fields
// with *Set suffix are set in the config. Note that the storage-related
// fields are NOT set in the config here but in the storage.conf OR directly
@@ -313,7 +311,7 @@ func readConfigFromFile(path string) (*Config, error) {
config.TmpDirSet = true
}
- return &config, err
+ return config, err
}
// Write decodes the config as TOML and writes it to the specified path.
@@ -439,15 +437,11 @@ func probeConmon(conmonBinary string) error {
// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This
// might change in the future.
func NewConfig(userConfigPath string) (*Config, error) {
- config := &Config{} // start with an empty config
-
- // First, try to read the user-specified config
- if userConfigPath != "" {
- var err error
- config, err = readConfigFromFile(userConfigPath)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath)
- }
+ // Start with the default config and interatively merge fields in the system
+ // configs.
+ config, err := defaultConfigFromMemory()
+ if err != nil {
+ return nil, err
}
// Now, check if the user can access system configs and merge them if needed.
@@ -456,44 +450,45 @@ func NewConfig(userConfigPath string) (*Config, error) {
return nil, errors.Wrapf(err, "error finding config on system")
}
- migrated := false
for _, path := range configs {
- systemConfig, err := readConfigFromFile(path)
+ config, err = readConfigFromFile(path, config)
if err != nil {
return nil, errors.Wrapf(err, "error reading system config %q", path)
}
- // Handle CGroups v2 configuration migration.
- // Migrate only the first config, and do it before
- // merging.
- if !migrated {
- if err := cgroupV2Check(path, systemConfig); err != nil {
- return nil, errors.Wrapf(err, "error rewriting configuration file %s", userConfigPath)
- }
- migrated = true
- }
- // Merge the it into the config. Any unset field in config will be
- // over-written by the systemConfig.
- if err := config.mergeConfig(systemConfig); err != nil {
- return nil, errors.Wrapf(err, "error merging system config")
- }
- logrus.Debugf("Merged system config %q: %v", path, config)
}
- // Finally, create a default config from memory and forcefully merge it into
- // the config. This way we try to make sure that all fields are properly set
- // and that user AND system config can partially set.
- defaultConfig, err := defaultConfigFromMemory()
- if err != nil {
- return nil, errors.Wrapf(err, "error generating default config from memory")
+ // First, try to read the user-specified config
+ if userConfigPath != "" {
+ var err error
+ config, err = readConfigFromFile(userConfigPath, config)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath)
+ }
}
- // Check if we need to switch to cgroupfs and logger=file on rootless.
- defaultConfig.checkCgroupsAndLogger()
-
- if err := config.mergeConfig(defaultConfig); err != nil {
- return nil, errors.Wrapf(err, "error merging default config from memory")
+ // Since runc does not currently support cgroupV2
+ // Change to default crun on first running of libpod.conf
+ // TODO Once runc has support for cgroups, this function should be removed.
+ if !config.CgroupCheck && rootless.IsRootless() {
+ cgroupsV2, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return nil, err
+ }
+ if cgroupsV2 {
+ path, err := exec.LookPath("crun")
+ if err != nil {
+ // Can't find crun path so do nothing
+ logrus.Warnf("Can not find crun package on the host, containers might fail to run on cgroup V2 systems without crun: %q", err)
+ } else {
+ config.CgroupCheck = true
+ config.OCIRuntime = path
+ }
+ }
}
+ // If we need to, switch to cgroupfs and logger=file on rootless.
+ config.checkCgroupsAndLogger()
+
// Relative paths can cause nasty bugs, because core paths we use could
// shift between runs (or even parts of the program - the OCI runtime
// uses a different working directory than we do, for example.
@@ -532,12 +527,12 @@ func systemConfigs() ([]string, error) {
}
configs := []string{}
- if _, err := os.Stat(_rootOverrideConfigPath); err == nil {
- configs = append(configs, _rootOverrideConfigPath)
- }
if _, err := os.Stat(_rootConfigPath); err == nil {
configs = append(configs, _rootConfigPath)
}
+ if _, err := os.Stat(_rootOverrideConfigPath); err == nil {
+ configs = append(configs, _rootOverrideConfigPath)
+ }
return configs, nil
}
@@ -568,29 +563,56 @@ func (c *Config) checkCgroupsAndLogger() {
}
}
-// Since runc does not currently support cgroupV2
-// Change to default crun on first running of libpod.conf
-// TODO Once runc has support for cgroups, this function should be removed.
-func cgroupV2Check(configPath string, tmpConfig *Config) error {
- if !tmpConfig.CgroupCheck && rootless.IsRootless() {
- logrus.Debugf("Rewriting %s for CGroup v2 upgrade", configPath)
- cgroupsV2, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return err
+// MergeDBConfig merges the configuration from the database.
+func (c *Config) MergeDBConfig(dbConfig *DBConfig) error {
+
+ if !c.StorageConfigRunRootSet && dbConfig.StorageTmp != "" {
+ if c.StorageConfig.RunRoot != dbConfig.StorageTmp &&
+ c.StorageConfig.RunRoot != "" {
+ logrus.Debugf("Overriding run root %q with %q from database",
+ c.StorageConfig.RunRoot, dbConfig.StorageTmp)
}
- if cgroupsV2 {
- path, err := exec.LookPath("crun")
- if err != nil {
- logrus.Warnf("Can not find crun package on the host, containers might fail to run on cgroup V2 systems without crun: %q", err)
- // Can't find crun path so do nothing
- return nil
- }
- tmpConfig.CgroupCheck = true
- tmpConfig.OCIRuntime = path
- if err := tmpConfig.Write(configPath); err != nil {
- return err
- }
+ c.StorageConfig.RunRoot = dbConfig.StorageTmp
+ }
+
+ if !c.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" {
+ if c.StorageConfig.GraphRoot != dbConfig.StorageRoot &&
+ c.StorageConfig.GraphRoot != "" {
+ logrus.Debugf("Overriding graph root %q with %q from database",
+ c.StorageConfig.GraphRoot, dbConfig.StorageRoot)
+ }
+ c.StorageConfig.GraphRoot = dbConfig.StorageRoot
+ }
+
+ if !c.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" {
+ if c.StorageConfig.GraphDriverName != dbConfig.GraphDriver &&
+ c.StorageConfig.GraphDriverName != "" {
+ logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
+ c.StorageConfig.GraphDriverName, dbConfig.GraphDriver)
+ }
+ c.StorageConfig.GraphDriverName = dbConfig.GraphDriver
+ }
+
+ if !c.StaticDirSet && dbConfig.LibpodRoot != "" {
+ if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" {
+ logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot)
+ }
+ c.StaticDir = dbConfig.LibpodRoot
+ }
+
+ if !c.TmpDirSet && dbConfig.LibpodTmp != "" {
+ if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" {
+ logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp)
+ }
+ c.TmpDir = dbConfig.LibpodTmp
+ c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log")
+ }
+
+ if !c.VolumePathSet && dbConfig.VolumePath != "" {
+ if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" {
+ logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath)
}
+ c.VolumePath = dbConfig.VolumePath
}
return nil
}
diff --git a/libpod/config/config_test.go b/libpod/config/config_test.go
index 47c092440..24620ce0e 100644
--- a/libpod/config/config_test.go
+++ b/libpod/config/config_test.go
@@ -11,14 +11,14 @@ import (
func TestEmptyConfig(t *testing.T) {
// Make sure that we can read empty configs
- config, err := readConfigFromFile("testdata/empty.conf")
+ config, err := readConfigFromFile("testdata/empty.conf", &Config{})
assert.NotNil(t, config)
assert.Nil(t, err)
}
func TestDefaultLibpodConf(t *testing.T) {
// Make sure that we can read the default libpod.conf
- config, err := readConfigFromFile("testdata/libpod.conf")
+ config, err := readConfigFromFile("testdata/libpod.conf", &Config{})
assert.NotNil(t, config)
assert.Nil(t, err)
}
@@ -32,13 +32,10 @@ func TestMergeEmptyAndDefaultMemoryConfig(t *testing.T) {
defaultConfig.StateType = define.InvalidStateStore
defaultConfig.StorageConfig = storage.StoreOptions{}
- emptyConfig, err := readConfigFromFile("testdata/empty.conf")
+ emptyConfig, err := readConfigFromFile("testdata/empty.conf", defaultConfig)
assert.NotNil(t, emptyConfig)
assert.Nil(t, err)
- err = emptyConfig.mergeConfig(defaultConfig)
- assert.Nil(t, err)
-
equal := reflect.DeepEqual(emptyConfig, defaultConfig)
assert.True(t, equal)
}
@@ -46,19 +43,16 @@ func TestMergeEmptyAndDefaultMemoryConfig(t *testing.T) {
func TestMergeEmptyAndLibpodConfig(t *testing.T) {
// Make sure that when we merge the default config into an empty one that we
// effectively get the default config.
- libpodConfig, err := readConfigFromFile("testdata/libpod.conf")
+ libpodConfig, err := readConfigFromFile("testdata/libpod.conf", &Config{})
assert.NotNil(t, libpodConfig)
assert.Nil(t, err)
libpodConfig.StateType = define.InvalidStateStore
libpodConfig.StorageConfig = storage.StoreOptions{}
- emptyConfig, err := readConfigFromFile("testdata/empty.conf")
+ emptyConfig, err := readConfigFromFile("testdata/empty.conf", libpodConfig)
assert.NotNil(t, emptyConfig)
assert.Nil(t, err)
- err = emptyConfig.mergeConfig(libpodConfig)
- assert.Nil(t, err)
-
equal := reflect.DeepEqual(emptyConfig, libpodConfig)
assert.True(t, equal)
}
diff --git a/libpod/config/merge.go b/libpod/config/merge.go
deleted file mode 100644
index 798a63da7..000000000
--- a/libpod/config/merge.go
+++ /dev/null
@@ -1,183 +0,0 @@
-package config
-
-import (
- "path/filepath"
-
- "github.com/containers/libpod/libpod/define"
- "github.com/sirupsen/logrus"
-)
-
-// Merge merges the other config into the current one. Note that a field of the
-// other config is only merged when it's not already set in the current one.
-//
-// Note that the StateType and the StorageConfig will NOT be changed.
-func (c *Config) mergeConfig(other *Config) error {
- // strings
- c.CgroupManager = mergeStrings(c.CgroupManager, other.CgroupManager)
- c.CNIConfigDir = mergeStrings(c.CNIConfigDir, other.CNIConfigDir)
- c.CNIDefaultNetwork = mergeStrings(c.CNIDefaultNetwork, other.CNIDefaultNetwork)
- c.DefaultMountsFile = mergeStrings(c.DefaultMountsFile, other.DefaultMountsFile)
- c.DetachKeys = mergeStrings(c.DetachKeys, other.DetachKeys)
- c.EventsLogFilePath = mergeStrings(c.EventsLogFilePath, other.EventsLogFilePath)
- c.EventsLogger = mergeStrings(c.EventsLogger, other.EventsLogger)
- c.ImageDefaultTransport = mergeStrings(c.ImageDefaultTransport, other.ImageDefaultTransport)
- c.InfraCommand = mergeStrings(c.InfraCommand, other.InfraCommand)
- c.InfraImage = mergeStrings(c.InfraImage, other.InfraImage)
- c.InitPath = mergeStrings(c.InitPath, other.InitPath)
- c.LockType = mergeStrings(c.LockType, other.LockType)
- c.Namespace = mergeStrings(c.Namespace, other.Namespace)
- c.NetworkCmdPath = mergeStrings(c.NetworkCmdPath, other.NetworkCmdPath)
- c.OCIRuntime = mergeStrings(c.OCIRuntime, other.OCIRuntime)
- c.SignaturePolicyPath = mergeStrings(c.SignaturePolicyPath, other.SignaturePolicyPath)
- c.StaticDir = mergeStrings(c.StaticDir, other.StaticDir)
- c.TmpDir = mergeStrings(c.TmpDir, other.TmpDir)
- c.VolumePath = mergeStrings(c.VolumePath, other.VolumePath)
-
- // string map of slices
- c.OCIRuntimes = mergeStringMaps(c.OCIRuntimes, other.OCIRuntimes)
-
- // string slices
- c.CNIPluginDir = mergeStringSlices(c.CNIPluginDir, other.CNIPluginDir)
- c.ConmonEnvVars = mergeStringSlices(c.ConmonEnvVars, other.ConmonEnvVars)
- c.ConmonPath = mergeStringSlices(c.ConmonPath, other.ConmonPath)
- c.HooksDir = mergeStringSlices(c.HooksDir, other.HooksDir)
- c.RuntimePath = mergeStringSlices(c.RuntimePath, other.RuntimePath)
- c.RuntimeSupportsJSON = mergeStringSlices(c.RuntimeSupportsJSON, other.RuntimeSupportsJSON)
- c.RuntimeSupportsNoCgroups = mergeStringSlices(c.RuntimeSupportsNoCgroups, other.RuntimeSupportsNoCgroups)
-
- // int64s
- c.MaxLogSize = mergeInt64s(c.MaxLogSize, other.MaxLogSize)
-
- // uint32s
- c.NumLocks = mergeUint32s(c.NumLocks, other.NumLocks)
-
- // bools
- c.EnableLabeling = mergeBools(c.EnableLabeling, other.EnableLabeling)
- c.EnablePortReservation = mergeBools(c.EnablePortReservation, other.EnablePortReservation)
- c.NoPivotRoot = mergeBools(c.NoPivotRoot, other.NoPivotRoot)
- c.SDNotify = mergeBools(c.SDNotify, other.SDNotify)
-
- // state type
- if c.StateType == define.InvalidStateStore {
- c.StateType = other.StateType
- }
-
- // store options - need to check all fields since some configs might only
- // set it partially
- c.StorageConfig.RunRoot = mergeStrings(c.StorageConfig.RunRoot, other.StorageConfig.RunRoot)
- c.StorageConfig.GraphRoot = mergeStrings(c.StorageConfig.GraphRoot, other.StorageConfig.GraphRoot)
- c.StorageConfig.GraphDriverName = mergeStrings(c.StorageConfig.GraphDriverName, other.StorageConfig.GraphDriverName)
- c.StorageConfig.GraphDriverOptions = mergeStringSlices(c.StorageConfig.GraphDriverOptions, other.StorageConfig.GraphDriverOptions)
- if c.StorageConfig.UIDMap == nil {
- c.StorageConfig.UIDMap = other.StorageConfig.UIDMap
- }
- if c.StorageConfig.GIDMap == nil {
- c.StorageConfig.GIDMap = other.StorageConfig.GIDMap
- }
-
- // backwards compat *Set fields
- c.StorageConfigRunRootSet = mergeBools(c.StorageConfigRunRootSet, other.StorageConfigRunRootSet)
- c.StorageConfigGraphRootSet = mergeBools(c.StorageConfigGraphRootSet, other.StorageConfigGraphRootSet)
- c.StorageConfigGraphDriverNameSet = mergeBools(c.StorageConfigGraphDriverNameSet, other.StorageConfigGraphDriverNameSet)
- c.VolumePathSet = mergeBools(c.VolumePathSet, other.VolumePathSet)
- c.StaticDirSet = mergeBools(c.StaticDirSet, other.StaticDirSet)
- c.TmpDirSet = mergeBools(c.TmpDirSet, other.TmpDirSet)
-
- return nil
-}
-
-// MergeDBConfig merges the configuration from the database.
-func (c *Config) MergeDBConfig(dbConfig *DBConfig) error {
-
- if !c.StorageConfigRunRootSet && dbConfig.StorageTmp != "" {
- if c.StorageConfig.RunRoot != dbConfig.StorageTmp &&
- c.StorageConfig.RunRoot != "" {
- logrus.Debugf("Overriding run root %q with %q from database",
- c.StorageConfig.RunRoot, dbConfig.StorageTmp)
- }
- c.StorageConfig.RunRoot = dbConfig.StorageTmp
- }
-
- if !c.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" {
- if c.StorageConfig.GraphRoot != dbConfig.StorageRoot &&
- c.StorageConfig.GraphRoot != "" {
- logrus.Debugf("Overriding graph root %q with %q from database",
- c.StorageConfig.GraphRoot, dbConfig.StorageRoot)
- }
- c.StorageConfig.GraphRoot = dbConfig.StorageRoot
- }
-
- if !c.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" {
- if c.StorageConfig.GraphDriverName != dbConfig.GraphDriver &&
- c.StorageConfig.GraphDriverName != "" {
- logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
- c.StorageConfig.GraphDriverName, dbConfig.GraphDriver)
- }
- c.StorageConfig.GraphDriverName = dbConfig.GraphDriver
- }
-
- if !c.StaticDirSet && dbConfig.LibpodRoot != "" {
- if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" {
- logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot)
- }
- c.StaticDir = dbConfig.LibpodRoot
- }
-
- if !c.TmpDirSet && dbConfig.LibpodTmp != "" {
- if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" {
- logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp)
- }
- c.TmpDir = dbConfig.LibpodTmp
- c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log")
- }
-
- if !c.VolumePathSet && dbConfig.VolumePath != "" {
- if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" {
- logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath)
- }
- c.VolumePath = dbConfig.VolumePath
- }
- return nil
-}
-
-func mergeStrings(a, b string) string {
- if a == "" {
- return b
- }
- return a
-}
-
-func mergeStringSlices(a, b []string) []string {
- if len(a) == 0 && b != nil {
- return b
- }
- return a
-}
-
-func mergeStringMaps(a, b map[string][]string) map[string][]string {
- if len(a) == 0 && b != nil {
- return b
- }
- return a
-}
-
-func mergeInt64s(a, b int64) int64 {
- if a == 0 {
- return b
- }
- return a
-}
-
-func mergeUint32s(a, b uint32) uint32 {
- if a == 0 {
- return b
- }
- return a
-}
-
-func mergeBools(a, b bool) bool {
- if !a {
- return b
- }
- return a
-}
diff --git a/libpod/config/merge_test.go b/libpod/config/merge_test.go
deleted file mode 100644
index eb450b273..000000000
--- a/libpod/config/merge_test.go
+++ /dev/null
@@ -1,157 +0,0 @@
-package config
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestMergeStrings(t *testing.T) {
- testData := []struct {
- a string
- b string
- res string
- }{
- {"", "", ""},
- {"a", "", "a"},
- {"a", "b", "a"},
- {"", "b", "b"},
- }
- for _, data := range testData {
- res := mergeStrings(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
-
-func TestMergeStringSlices(t *testing.T) {
- testData := []struct {
- a []string
- b []string
- res []string
- }{
- {
- nil, nil, nil,
- },
- {
- nil,
- []string{},
- []string{},
- },
- {
- []string{},
- nil,
- []string{},
- },
- {
- []string{},
- []string{},
- []string{},
- },
- {
- []string{"a"},
- []string{},
- []string{"a"},
- },
- {
- []string{"a"},
- []string{"b"},
- []string{"a"},
- },
- {
- []string{},
- []string{"b"},
- []string{"b"},
- },
- }
- for _, data := range testData {
- res := mergeStringSlices(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
-
-func TestMergeStringMaps(t *testing.T) {
- testData := []struct {
- a map[string][]string
- b map[string][]string
- res map[string][]string
- }{
- {
- nil, nil, nil,
- },
- {
- nil,
- map[string][]string{},
- map[string][]string{}},
- {
- map[string][]string{"a": {"a"}},
- nil,
- map[string][]string{"a": {"a"}},
- },
- {
- nil,
- map[string][]string{"b": {"b"}},
- map[string][]string{"b": {"b"}},
- },
- {
- map[string][]string{"a": {"a"}},
- map[string][]string{"b": {"b"}},
- map[string][]string{"a": {"a"}},
- },
- }
- for _, data := range testData {
- res := mergeStringMaps(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
-
-func TestMergeInts64(t *testing.T) {
- testData := []struct {
- a int64
- b int64
- res int64
- }{
- {int64(0), int64(0), int64(0)},
- {int64(1), int64(0), int64(1)},
- {int64(0), int64(1), int64(1)},
- {int64(2), int64(1), int64(2)},
- {int64(-1), int64(1), int64(-1)},
- {int64(0), int64(-1), int64(-1)},
- }
- for _, data := range testData {
- res := mergeInt64s(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
-func TestMergeUint32(t *testing.T) {
- testData := []struct {
- a uint32
- b uint32
- res uint32
- }{
- {uint32(0), uint32(0), uint32(0)},
- {uint32(1), uint32(0), uint32(1)},
- {uint32(0), uint32(1), uint32(1)},
- {uint32(2), uint32(1), uint32(2)},
- }
- for _, data := range testData {
- res := mergeUint32s(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
-
-func TestMergeBools(t *testing.T) {
- testData := []struct {
- a bool
- b bool
- res bool
- }{
- {false, false, false},
- {true, false, true},
- {false, true, true},
- {true, true, true},
- }
- for _, data := range testData {
- res := mergeBools(data.a, data.b)
- assert.Equal(t, data.res, res)
- }
-}
diff --git a/libpod/container.go b/libpod/container.go
index 5e5c8ab26..dbd15e55f 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -249,8 +249,6 @@ type ContainerConfig struct {
RootfsImageName string `json:"rootfsImageName,omitempty"`
// Rootfs to use for the container, this conflicts with RootfsImageID
Rootfs string `json:"rootfs,omitempty"`
- // Whether to mount volumes specified in the image.
- ImageVolumes bool `json:"imageVolumes"`
// Src path to be mounted on /dev/shm in container.
ShmDir string `json:"ShmDir,omitempty"`
// Size of the container's SHM.
@@ -510,12 +508,6 @@ func (c *Container) Image() (string, string) {
return c.config.RootfsImageID, c.config.RootfsImageName
}
-// ImageVolumes returns whether the container is configured to create
-// persistent volumes requested by the image
-func (c *Container) ImageVolumes() bool {
- return c.config.ImageVolumes
-}
-
// ShmDir returns the sources path to be mounted on /dev/shm in container
func (c *Container) ShmDir() string {
return c.config.ShmDir
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 641bc8a91..a543a19c0 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -606,11 +606,45 @@ type InspectContainerState struct {
Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"`
}
+// InspectBasicNetworkConfig holds basic configuration information (e.g. IP
+// addresses, MAC address, subnet masks, etc) that are common for all networks
+// (both additional and main).
+type InspectBasicNetworkConfig struct {
+ // EndpointID is unused, maintained exclusively for compatibility.
+ EndpointID string `json:"EndpointID"`
+ // Gateway is the IP address of the gateway this network will use.
+ Gateway string `json:"Gateway"`
+ // IPAddress is the IP address for this network.
+ IPAddress string `json:"IPAddress"`
+ // IPPrefixLen is the length of the subnet mask of this network.
+ IPPrefixLen int `json:"IPPrefixLen"`
+ // SecondaryIPAddresses is a list of extra IP Addresses that the
+ // container has been assigned in this network.
+ SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty"`
+ // IPv6Gateway is the IPv6 gateway this network will use.
+ IPv6Gateway string `json:"IPv6Gateway"`
+ // GlobalIPv6Address is the global-scope IPv6 Address for this network.
+ GlobalIPv6Address string `json:"GlobalIPv6Address"`
+ // GlobalIPv6PrefixLen is the length of the subnet mask of this network.
+ GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"`
+ // SecondaryIPv6Addresses is a list of extra IPv6 Addresses that the
+ // container has been assigned in this networ.
+ SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty"`
+ // MacAddress is the MAC address for the interface in this network.
+ MacAddress string `json:"MacAddress"`
+ // AdditionalMacAddresses is a set of additional MAC Addresses beyond
+ // the first. CNI may configure more than one interface for a single
+ // network, which can cause this.
+ AdditionalMacAddresses []string `json:"AdditionalMACAddresses,omitempty"`
+}
+
// InspectNetworkSettings holds information about the network settings of the
// container.
// Many fields are maintained only for compatibility with `docker inspect` and
// are unused within Libpod.
type InspectNetworkSettings struct {
+ InspectBasicNetworkConfig
+
Bridge string `json:"Bridge"`
SandboxID string `json:"SandboxID"`
HairpinMode bool `json:"HairpinMode"`
@@ -618,16 +652,30 @@ type InspectNetworkSettings struct {
LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"`
Ports []ocicni.PortMapping `json:"Ports"`
SandboxKey string `json:"SandboxKey"`
- SecondaryIPAddresses []string `json:"SecondaryIPAddresses"`
- SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses"`
- EndpointID string `json:"EndpointID"`
- Gateway string `json:"Gateway"`
- GlobalIPv6Address string `json:"GlobalIPv6Address"`
- GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"`
- IPAddress string `json:"IPAddress"`
- IPPrefixLen int `json:"IPPrefixLen"`
- IPv6Gateway string `json:"IPv6Gateway"`
- MacAddress string `json:"MacAddress"`
+ // Networks contains information on non-default CNI networks this
+ // container has joined.
+ // It is a map of network name to network information.
+ Networks map[string]*InspectAdditionalNetwork `json:"Networks,omitempty"`
+}
+
+// InspectAdditionalNetwork holds information about non-default CNI networks the
+// container has been connected to.
+// As with InspectNetworkSettings, many fields are unused and maintained only
+// for compatibility with Docker.
+type InspectAdditionalNetwork struct {
+ InspectBasicNetworkConfig
+
+ // Name of the network we're connecting to.
+ NetworkID string `json:"NetworkID,omitempty"`
+ // DriverOpts is presently unused and maintained exclusively for
+ // compatibility.
+ DriverOpts map[string]string `json:"DriverOpts"`
+ // IPAMConfig is presently unused and maintained exlusively for
+ // compabitility.
+ IPAMConfig map[string]string `json:"IPAMConfig"`
+ // Links is presently unused and maintained exclusively for
+ // compatibility.
+ Links []string `json:"Links"`
}
// inspectLocked inspects a container for low-level information.
@@ -754,27 +802,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
GraphDriver: driverData,
Mounts: inspectMounts,
Dependencies: c.Dependencies(),
- NetworkSettings: &InspectNetworkSettings{
- Bridge: "", // TODO
- SandboxID: "", // TODO - is this even relevant?
- HairpinMode: false, // TODO
- LinkLocalIPv6Address: "", // TODO - do we even support IPv6?
- LinkLocalIPv6PrefixLen: 0, // TODO - do we even support IPv6?
-
- Ports: []ocicni.PortMapping{}, // TODO - maybe worth it to put this in Docker format?
- SandboxKey: "", // Network namespace path
- SecondaryIPAddresses: nil, // TODO - do we support this?
- SecondaryIPv6Addresses: nil, // TODO - do we support this?
- EndpointID: "", // TODO - is this even relevant?
- Gateway: "", // TODO
- GlobalIPv6Address: "",
- GlobalIPv6PrefixLen: 0,
- IPAddress: "",
- IPPrefixLen: 0,
- IPv6Gateway: "",
- MacAddress: "", // TODO
- },
- IsInfra: c.IsInfra(),
+ IsInfra: c.IsInfra(),
}
if c.state.ConfigPath != "" {
@@ -792,13 +820,11 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
}
}
- // Copy port mappings into network settings
- if config.PortMappings != nil {
- data.NetworkSettings.Ports = config.PortMappings
+ networkConfig, err := c.getContainerNetworkInfo()
+ if err != nil {
+ return nil, err
}
-
- // Get information on the container's network namespace (if present)
- data = c.getContainerNetworkInfo(data)
+ data.NetworkSettings = networkConfig
inspectConfig, err := c.generateInspectContainerConfig(ctrSpec)
if err != nil {
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 216bbe669..ff43bfc8f 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -914,6 +914,7 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
func (c *Container) completeNetworkSetup() error {
+ var outResolvConf []string
netDisabled, err := c.NetworkDisabled()
if err != nil {
return err
@@ -927,7 +928,37 @@ func (c *Container) completeNetworkSetup() error {
if c.config.NetMode == "slirp4netns" {
return c.runtime.setupRootlessNetNS(c)
}
- return c.runtime.setupNetNS(c)
+ if err := c.runtime.setupNetNS(c); err != nil {
+ return err
+ }
+ state := c.state
+ // collect any dns servers that cni tells us to use (dnsname)
+ for _, cni := range state.NetworkStatus {
+ if cni.DNS.Nameservers != nil {
+ for _, server := range cni.DNS.Nameservers {
+ outResolvConf = append(outResolvConf, fmt.Sprintf("nameserver %s", server))
+ }
+ }
+ }
+ // check if we have a bindmount for resolv.conf
+ resolvBindMount := state.BindMounts["/etc/resolv.conf"]
+ if len(outResolvConf) < 1 || resolvBindMount == "" || len(c.config.NetNsCtr) > 0 {
+ return nil
+ }
+ // read the existing resolv.conf
+ b, err := ioutil.ReadFile(resolvBindMount)
+ if err != nil {
+ return err
+ }
+ for _, line := range strings.Split(string(b), "\n") {
+ // only keep things that dont start with nameserver from the old
+ // resolv.conf file
+ if !strings.HasPrefix(line, "nameserver") {
+ outResolvConf = append([]string{line}, outResolvConf...)
+ }
+ }
+ // write and return
+ return ioutil.WriteFile(resolvBindMount, []byte(strings.Join(outResolvConf, "\n")), 0644)
}
// Initialize a container, creating it in the runtime
@@ -1370,6 +1401,9 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
return nil, errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID())
}
+ if vol.config.LockID == c.config.LockID {
+ return nil, errors.Wrapf(define.ErrWillDeadlock, "container %s and volume %s share lock ID %d", c.ID(), vol.Name(), c.config.LockID)
+ }
vol.lock.Lock()
defer vol.lock.Unlock()
if vol.needsMount() {
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 561dbdc1c..739026264 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1114,22 +1114,17 @@ func (c *Container) makeBindMounts() error {
return errors.Wrapf(err, "error fetching bind mounts from dependency %s of container %s", depCtr.ID(), c.ID())
}
- if !c.config.UseImageResolvConf {
- // The other container may not have a resolv.conf or /etc/hosts
- // If it doesn't, don't copy them
- resolvPath, exists := bindMounts["/etc/resolv.conf"]
- if exists {
- c.state.BindMounts["/etc/resolv.conf"] = resolvPath
- }
+ // The other container may not have a resolv.conf or /etc/hosts
+ // If it doesn't, don't copy them
+ resolvPath, exists := bindMounts["/etc/resolv.conf"]
+ if !c.config.UseImageResolvConf && exists {
+ c.state.BindMounts["/etc/resolv.conf"] = resolvPath
}
- if !c.config.UseImageHosts {
- // check if dependency container has an /etc/hosts file
- hostsPath, exists := bindMounts["/etc/hosts"]
- if !exists {
- return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
- }
-
+ // check if dependency container has an /etc/hosts file.
+ // It may not have one, so only use it if it does.
+ hostsPath, exists := bindMounts["/etc/hosts"]
+ if !c.config.UseImageHosts && exists {
depCtr.lock.Lock()
// generate a hosts file for the dependency container,
// based on either its old hosts file, or the default,
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index c4acc3d4f..748715ed3 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -40,7 +40,7 @@ func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *l
defaultTime := time.Time{}
if options.Since != defaultTime {
// coreos/go-systemd/sdjournal doesn't correctly handle requests for data in the future
- // return nothing instead of fasely printing
+ // return nothing instead of falsely printing
if time.Now().Before(options.Since) {
return nil
}
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index 523062866..b79cf08dc 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -61,6 +61,11 @@ var (
// the user.
ErrDetach = utils.ErrDetach
+ // ErrWillDeadlock indicates that the requested operation will cause a
+ // deadlock. This is usually caused by upgrade issues, and is resolved
+ // by renumbering the locks.
+ ErrWillDeadlock = errors.New("deadlock due to lock mismatch")
+
// ErrNoCgroups indicates that the container does not have its own
// CGroup.
ErrNoCgroups = errors.New("this container does not have a cgroup")
diff --git a/libpod/image/filters.go b/libpod/image/filters.go
index d545f1bfc..c54ca6333 100644
--- a/libpod/image/filters.go
+++ b/libpod/image/filters.go
@@ -102,6 +102,13 @@ func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter {
}
}
+// IdFilter allows you to filter by image Id
+func IdFilter(idFilter string) ResultFilter {
+ return func(i *Image) bool {
+ return i.ID() == idFilter
+ }
+}
+
// OutputImageFilter allows you to filter by an a specific image name
func OutputImageFilter(userImage *Image) ResultFilter {
return func(i *Image) bool {
@@ -141,7 +148,7 @@ func (ir *Runtime) createFilterFuncs(filters []string, img *Image) ([]ResultFilt
return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1])
}
filterFuncs = append(filterFuncs, CreatedBeforeFilter(before.Created()))
- case "after":
+ case "since", "after":
after, err := ir.NewFromLocal(splitFilter[1])
if err != nil {
return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1])
@@ -165,6 +172,8 @@ func (ir *Runtime) createFilterFuncs(filters []string, img *Image) ([]ResultFilt
case "reference":
referenceFilter := strings.Join(splitFilter[1:], "=")
filterFuncs = append(filterFuncs, ReferenceFilter(ctx, referenceFilter))
+ case "id":
+ filterFuncs = append(filterFuncs, IdFilter(splitFilter[1]))
default:
return nil, errors.Errorf("invalid filter %s ", splitFilter[0])
}
diff --git a/libpod/logs/log.go b/libpod/logs/log.go
index c2ce1e426..200ef3e99 100644
--- a/libpod/logs/log.go
+++ b/libpod/logs/log.go
@@ -2,13 +2,16 @@ package logs
import (
"fmt"
- "io/ioutil"
+ "io"
+ "os"
"strings"
"sync"
"time"
+ "github.com/containers/libpod/libpod/logs/reversereader"
"github.com/hpcloud/tail"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
const (
@@ -76,43 +79,84 @@ func GetLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error
func getTailLog(path string, tail int) ([]*LogLine, error) {
var (
- tailLog []*LogLine
- nlls []*LogLine
- tailCounter int
- partial string
+ nlls []*LogLine
+ nllCounter int
+ leftover string
+ partial string
+ tailLog []*LogLine
)
- content, err := ioutil.ReadFile(path)
+ f, err := os.Open(path)
if err != nil {
return nil, err
}
- splitContent := strings.Split(string(content), "\n")
- // We read the content in reverse and add each nll until we have the same
- // number of F type messages as the desired tail
- for i := len(splitContent) - 1; i >= 0; i-- {
- if len(splitContent[i]) == 0 {
- continue
- }
- nll, err := NewLogLine(splitContent[i])
- if err != nil {
- return nil, err
+ rr, err := reversereader.NewReverseReader(f)
+ if err != nil {
+ return nil, err
+ }
+
+ inputs := make(chan []string)
+ go func() {
+ for {
+ s, err := rr.Read()
+ if err != nil {
+ if errors.Cause(err) == io.EOF {
+ inputs <- []string{leftover}
+ close(inputs)
+ break
+ }
+ logrus.Error(err)
+ close(inputs)
+ }
+ line := strings.Split(s+leftover, "\n")
+ if len(line) > 1 {
+ inputs <- line[1:]
+ }
+ leftover = line[0]
}
- nlls = append(nlls, nll)
- if !nll.Partial() {
- tailCounter++
+ }()
+
+ for i := range inputs {
+ // the incoming array is FIFO; we want FIFO so
+ // reverse the slice read order
+ for j := len(i) - 1; j >= 0; j-- {
+ // lines that are "" are junk
+ if len(i[j]) < 1 {
+ continue
+ }
+ // read the content in reverse and add each nll until we have the same
+ // number of F type messages as the desired tail
+ nll, err := NewLogLine(i[j])
+ if err != nil {
+ return nil, err
+ }
+ nlls = append(nlls, nll)
+ if !nll.Partial() {
+ nllCounter++
+ }
}
- if tailCounter == tail {
+ // if we have enough loglines, we can hangup
+ if nllCounter >= tail {
+ if err := f.Close(); err != nil {
+ logrus.Error(err)
+ }
break
}
}
- // Now we iterate the results and assemble partial messages to become full messages
+
+ // re-assemble the log lines and trim (if needed) to the
+ // tail length
for _, nll := range nlls {
if nll.Partial() {
partial += nll.Msg
} else {
nll.Msg += partial
- tailLog = append(tailLog, nll)
+ // prepend because we need to reverse the order again to FIFO
+ tailLog = append([]*LogLine{nll}, tailLog...)
partial = ""
}
+ if len(tailLog) == tail {
+ break
+ }
}
return tailLog, nil
}
diff --git a/libpod/logs/reversereader/reversereader.go b/libpod/logs/reversereader/reversereader.go
new file mode 100644
index 000000000..72d9ad975
--- /dev/null
+++ b/libpod/logs/reversereader/reversereader.go
@@ -0,0 +1,66 @@
+package reversereader
+
+import (
+ "io"
+ "os"
+
+ "github.com/pkg/errors"
+)
+
+// ReverseReader structure for reading a file backwards
+type ReverseReader struct {
+ reader *os.File
+ offset int64
+ readSize int64
+}
+
+// NewReverseReader returns a reader that reads from the end of a file
+// rather than the beginning. It sets the readsize to pagesize and determines
+// the first offset using using modulus.
+func NewReverseReader(reader *os.File) (*ReverseReader, error) {
+ // pagesize should be safe for memory use and file reads should be on page
+ // boundaries as well
+ pageSize := int64(os.Getpagesize())
+ stat, err := reader.Stat()
+ if err != nil {
+ return nil, err
+ }
+ // figure out the last page boundary
+ remainder := stat.Size() % pageSize
+ end, err := reader.Seek(0, 2)
+ if err != nil {
+ return nil, err
+ }
+ // set offset (starting position) to the last page boundary or
+ // zero if fits in one page
+ startOffset := end - remainder
+ if startOffset < 0 {
+ startOffset = 0
+ }
+ rr := ReverseReader{
+ reader: reader,
+ offset: startOffset,
+ readSize: pageSize,
+ }
+ return &rr, nil
+}
+
+// ReverseReader reads from a given offset to the previous offset and
+// then sets the newoff set one pagesize less than the previous read.
+func (r *ReverseReader) Read() (string, error) {
+ if r.offset < 0 {
+ return "", errors.Wrap(io.EOF, "at beginning of file")
+ }
+ // Read from given offset
+ b := make([]byte, r.readSize)
+ n, err := r.reader.ReadAt(b, r.offset)
+ if err != nil && errors.Cause(err) != io.EOF {
+ return "", err
+ }
+ if int64(n) < r.readSize {
+ b = b[0:n]
+ }
+ // Set to the next page boundary
+ r.offset = -r.readSize
+ return string(b), nil
+}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index d90bcb708..d57b1a8eb 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -12,13 +12,13 @@ import (
"os"
"os/exec"
"path/filepath"
- "strconv"
"strings"
"syscall"
"time"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/netns"
"github.com/containers/libpod/pkg/rootless"
@@ -335,10 +335,13 @@ func (r *Runtime) setupRootlessPortMapping(ctr *Container, netnsPath string) (er
return errors.Wrapf(err, "delete file %s", logPath)
}
- ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
- if err != nil {
- return errors.Wrapf(err, "failed to create rootless port sync pipe")
+ if !ctr.config.PostConfigureNetNS {
+ ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
+ if err != nil {
+ return errors.Wrapf(err, "failed to create rootless port sync pipe")
+ }
}
+
cfg := rootlessport.Config{
Mappings: ctr.config.PortMappings,
NetNSPath: netnsPath,
@@ -355,6 +358,11 @@ func (r *Runtime) setupRootlessPortMapping(ctr *Container, netnsPath string) (er
cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid()))
cmd.Args = []string{rootlessport.ReexecKey}
// Leak one end of the pipe in rootlessport process, the other will be sent to conmon
+
+ if ctr.rootlessPortSyncR != nil {
+ defer errorhandling.CloseQuiet(ctr.rootlessPortSyncR)
+ }
+
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessPortSyncR, syncW)
cmd.Stdin = cfgR
// stdout is for human-readable error, stderr is for debug log
@@ -548,37 +556,105 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
return netStats, err
}
-func (c *Container) getContainerNetworkInfo(data *InspectContainerData) *InspectContainerData {
- if c.state.NetNS != nil && len(c.state.NetworkStatus) > 0 {
- // Report network settings from the first pod network
- result := c.state.NetworkStatus[0]
- // Go through our IP addresses
- for _, ctrIP := range result.IPs {
- ipWithMask := ctrIP.Address.String()
- splitIP := strings.Split(ipWithMask, "/")
- mask, _ := strconv.Atoi(splitIP[1])
- if ctrIP.Version == "4" {
- data.NetworkSettings.IPAddress = splitIP[0]
- data.NetworkSettings.IPPrefixLen = mask
- data.NetworkSettings.Gateway = ctrIP.Gateway.String()
- } else {
- data.NetworkSettings.GlobalIPv6Address = splitIP[0]
- data.NetworkSettings.GlobalIPv6PrefixLen = mask
- data.NetworkSettings.IPv6Gateway = ctrIP.Gateway.String()
+// Produce an InspectNetworkSettings containing information on the container
+// network.
+func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) {
+ settings := new(InspectNetworkSettings)
+ settings.Ports = []ocicni.PortMapping{}
+ if c.config.PortMappings != nil {
+ // TODO: This may not be safe.
+ settings.Ports = c.config.PortMappings
+ }
+
+ // We can't do more if the network is down.
+ if c.state.NetNS == nil {
+ return settings, nil
+ }
+
+ // Set network namespace path
+ settings.SandboxKey = c.state.NetNS.Path()
+
+ // If this is empty, we're probably slirp4netns
+ if len(c.state.NetworkStatus) == 0 {
+ return settings, nil
+ }
+
+ // If we have CNI networks - handle that here
+ if len(c.config.Networks) > 0 {
+ if len(c.config.Networks) != len(c.state.NetworkStatus) {
+ return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(c.config.Networks), len(c.state.NetworkStatus))
+ }
+
+ settings.Networks = make(map[string]*InspectAdditionalNetwork)
+
+ // CNI results should be in the same order as the list of
+ // networks we pass into CNI.
+ for index, name := range c.config.Networks {
+ cniResult := c.state.NetworkStatus[index]
+ addedNet := new(InspectAdditionalNetwork)
+ addedNet.NetworkID = name
+
+ basicConfig, err := resultToBasicNetworkConfig(cniResult)
+ if err != nil {
+ return nil, err
}
+ addedNet.InspectBasicNetworkConfig = basicConfig
+
+ settings.Networks[name] = addedNet
+ }
+
+ return settings, nil
+ }
+
+ // If not joining networks, we should have at most 1 result
+ if len(c.state.NetworkStatus) > 1 {
+ return nil, errors.Wrapf(define.ErrInternal, "should have at most 1 CNI result if not joining networks, instead got %d", len(c.state.NetworkStatus))
+ }
+
+ if len(c.state.NetworkStatus) == 1 {
+ basicConfig, err := resultToBasicNetworkConfig(c.state.NetworkStatus[0])
+ if err != nil {
+ return nil, err
}
- // Set network namespace path
- data.NetworkSettings.SandboxKey = c.state.NetNS.Path()
+ settings.InspectBasicNetworkConfig = basicConfig
+ }
+
+ return settings, nil
+}
- // Set MAC address of interface linked with network namespace path
- for _, i := range result.Interfaces {
- if i.Sandbox == data.NetworkSettings.SandboxKey {
- data.NetworkSettings.MacAddress = i.Mac
+// resultToBasicNetworkConfig produces an InspectBasicNetworkConfig from a CNI
+// result
+func resultToBasicNetworkConfig(result *cnitypes.Result) (InspectBasicNetworkConfig, error) {
+ config := InspectBasicNetworkConfig{}
+
+ for _, ctrIP := range result.IPs {
+ size, _ := ctrIP.Address.Mask.Size()
+ switch {
+ case ctrIP.Version == "4" && config.IPAddress == "":
+ config.IPAddress = ctrIP.Address.IP.String()
+ config.IPPrefixLen = size
+ config.Gateway = ctrIP.Gateway.String()
+ if ctrIP.Interface != nil && *ctrIP.Interface < len(result.Interfaces) && *ctrIP.Interface > 0 {
+ config.MacAddress = result.Interfaces[*ctrIP.Interface].Mac
}
+ case ctrIP.Version == "4" && config.IPAddress != "":
+ config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, ctrIP.Address.String())
+ if ctrIP.Interface != nil && *ctrIP.Interface < len(result.Interfaces) && *ctrIP.Interface > 0 {
+ config.AdditionalMacAddresses = append(config.AdditionalMacAddresses, result.Interfaces[*ctrIP.Interface].Mac)
+ }
+ case ctrIP.Version == "6" && config.IPAddress == "":
+ config.GlobalIPv6Address = ctrIP.Address.IP.String()
+ config.GlobalIPv6PrefixLen = size
+ config.IPv6Gateway = ctrIP.Gateway.String()
+ case ctrIP.Version == "6" && config.IPAddress != "":
+ config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, ctrIP.Address.String())
+ default:
+ return config, errors.Wrapf(define.ErrInternal, "unrecognized IP version %q", ctrIP.Version)
}
}
- return data
+
+ return config, nil
}
type logrusDebugWriter struct {
diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go
index d9b3730aa..7f343cf35 100644
--- a/libpod/networking_unsupported.go
+++ b/libpod/networking_unsupported.go
@@ -20,6 +20,6 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) {
return define.ErrNotImplemented
}
-func (c *Container) getContainerNetworkInfo(data *InspectContainerData) *InspectContainerData {
- return nil
+func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) {
+ return nil, define.ErrNotImplemented
}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 722012386..07d38693f 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1161,6 +1161,13 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
if ctr.config.NetMode.IsSlirp4netns() {
if ctr.config.PostConfigureNetNS {
+ havePortMapping := len(ctr.Config().PortMappings) > 0
+ if havePortMapping {
+ ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
+ if err != nil {
+ return errors.Wrapf(err, "failed to create rootless port sync pipe")
+ }
+ }
ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe()
if err != nil {
return errors.Wrapf(err, "failed to create rootless network sync pipe")
@@ -1176,9 +1183,6 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// Leak one end in conmon, the other one will be leaked into slirp4netns
cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncW)
- if ctr.rootlessPortSyncR != nil {
- defer errorhandling.CloseQuiet(ctr.rootlessPortSyncR)
- }
if ctr.rootlessPortSyncW != nil {
defer errorhandling.CloseQuiet(ctr.rootlessPortSyncW)
// Leak one end in conmon, the other one will be leaked into rootlessport
diff --git a/libpod/options.go b/libpod/options.go
index 4957f822d..d01e8a85f 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -593,7 +593,7 @@ func WithUser(user string) CtrCreateOption {
// other configuration from the image will be added to the config.
// TODO: Replace image name and ID with a libpod.Image struct when that is
// finished.
-func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool) CtrCreateOption {
+func WithRootFSFromImage(imageID string, imageName string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return define.ErrCtrFinalized
@@ -608,7 +608,6 @@ func WithRootFSFromImage(imageID string, imageName string, useImageVolumes bool)
ctr.config.RootfsImageID = imageID
ctr.config.RootfsImageName = imageName
- ctr.config.ImageVolumes = useImageVolumes
return nil
}
@@ -953,6 +952,16 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo
return define.ErrCtrFinalized
}
+ if rootless.IsRootless() {
+ if len(networks) > 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot use CNI networks with rootless containers")
+ }
+ }
+
+ if len(networks) > 1 && (ctr.config.StaticIP != nil || ctr.config.StaticMAC != nil) {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot join more than one CNI network if configuring a static IP or MAC address")
+ }
+
if ctr.config.NetNsCtr != "" {
return errors.Wrapf(define.ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns")
}
@@ -962,12 +971,6 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo
ctr.config.CreateNetNS = true
ctr.config.PortMappings = portMappings
- if rootless.IsRootless() {
- if len(networks) > 0 {
- return errors.New("cannot use CNI networks with rootless containers")
- }
- }
-
ctr.config.Networks = networks
return nil
@@ -1780,6 +1783,9 @@ func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption {
if pod.valid {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set pod ports as no infra container is being created")
+ }
pod.config.InfraContainer.PortBindings = bindings
return nil
}
@@ -1792,6 +1798,14 @@ func WithPodStaticIP(ip net.IP) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static IP as no infra container is being created")
+ }
+
+ if pod.config.InfraContainer.HostNetwork {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP if host network is specified")
+ }
+
if len(pod.config.InfraContainer.Networks) > 1 {
return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining more than 1 CNI network")
}
@@ -1809,6 +1823,14 @@ func WithPodStaticMAC(mac net.HardwareAddr) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static MAC as no infra container is being created")
+ }
+
+ if pod.config.InfraContainer.HostNetwork {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set static MAC if host network is specified")
+ }
+
if len(pod.config.InfraContainer.Networks) > 1 {
return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining more than 1 CNI network")
}
@@ -1827,6 +1849,10 @@ func WithPodUseImageResolvConf() PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
+ }
+
if len(pod.config.InfraContainer.DNSServer) != 0 ||
len(pod.config.InfraContainer.DNSSearch) != 0 ||
len(pod.config.InfraContainer.DNSOption) != 0 {
@@ -1846,6 +1872,10 @@ func WithPodDNS(dnsServer []string) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
+ }
+
if pod.config.InfraContainer.UseImageResolvConf {
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if pod will not create /etc/resolv.conf")
}
@@ -1863,6 +1893,10 @@ func WithPodDNSSearch(dnsSearch []string) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
+ }
+
if pod.config.InfraContainer.UseImageResolvConf {
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if pod will not create /etc/resolv.conf")
}
@@ -1880,6 +1914,10 @@ func WithPodDNSOption(dnsOption []string) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created")
+ }
+
if pod.config.InfraContainer.UseImageResolvConf {
return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if pod will not create /etc/resolv.conf")
}
@@ -1898,6 +1936,10 @@ func WithPodUseImageHosts() PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
+ }
+
if len(pod.config.InfraContainer.HostAdd) != 0 {
return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
}
@@ -1915,6 +1957,10 @@ func WithPodHosts(hosts []string) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created")
+ }
+
if pod.config.InfraContainer.UseImageHosts {
return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if container is using image hosts")
}
@@ -1932,8 +1978,45 @@ func WithPodNetworks(networks []string) PodCreateOption {
return define.ErrPodFinalized
}
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod CNI networks as no infra container is being created")
+ }
+
+ if (pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil) &&
+ len(networks) > 1 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot join more than one CNI network if setting a static IP or MAC address")
+ }
+
+ if pod.config.InfraContainer.HostNetwork {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot join pod to CNI networks if host network is specified")
+ }
+
pod.config.InfraContainer.Networks = networks
return nil
}
}
+
+// WithPodHostNetwork tells the pod to use the host's network namespace.
+func WithPodHostNetwork() PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if !pod.config.InfraContainer.HasInfraContainer {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created")
+ }
+
+ if len(pod.config.InfraContainer.PortBindings) > 0 ||
+ pod.config.InfraContainer.StaticIP != nil ||
+ pod.config.InfraContainer.StaticMAC != nil ||
+ len(pod.config.InfraContainer.Networks) > 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
+ }
+
+ pod.config.InfraContainer.HostNetwork = true
+
+ return nil
+ }
+}
diff --git a/libpod/pod.go b/libpod/pod.go
index 4f85caf08..1b4c06c9d 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -99,6 +99,7 @@ type PodContainerInfo struct {
// InfraContainerConfig is the configuration for the pod's infra container
type InfraContainerConfig struct {
HasInfraContainer bool `json:"makeInfraContainer"`
+ HostNetwork bool `json:"infraHostNetwork,omitempty"`
PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
StaticIP net.IP `json:"staticIP,omitempty"`
StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 3ad09f27c..39284026c 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -412,6 +412,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool,
}
// Lock the pod while we're removing container
+ if pod.config.LockID == c.config.LockID {
+ return errors.Wrapf(define.ErrWillDeadlock, "container %s and pod %s share lock ID %d", c.ID(), pod.ID(), c.config.LockID)
+ }
pod.lock.Lock()
defer pod.lock.Unlock()
if err := pod.updatePod(); err != nil {
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 1b1421ca8..da46f03e8 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -37,6 +37,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
isRootless := rootless.IsRootless()
entryCmd := []string{r.config.InfraCommand}
+ var options []CtrCreateOption
// I've seen circumstances where config is being passed as nil.
// Let's err on the side of safety and make sure it's safe to use.
if config != nil {
@@ -68,6 +69,44 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
g.AddProcessEnv(nameValSlice[0], nameValSlice[1])
}
}
+
+ // Since user namespace sharing is not implemented, we only need to check if it's rootless
+ if !p.config.InfraContainer.HostNetwork {
+ netmode := "bridge"
+ if isRootless {
+ netmode = "slirp4netns"
+ }
+ // PostConfigureNetNS should not be set since user namespace sharing is not implemented
+ // and rootless networking no longer supports post configuration setup
+ options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks))
+ } else if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
+ return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID())
+ }
+
+ if p.config.InfraContainer.StaticIP != nil {
+ options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
+ }
+ if p.config.InfraContainer.StaticMAC != nil {
+ options = append(options, WithStaticMAC(p.config.InfraContainer.StaticMAC))
+ }
+ if p.config.InfraContainer.UseImageResolvConf {
+ options = append(options, WithUseImageResolvConf())
+ }
+ if len(p.config.InfraContainer.DNSServer) > 0 {
+ options = append(options, WithDNS(p.config.InfraContainer.DNSServer))
+ }
+ if len(p.config.InfraContainer.DNSSearch) > 0 {
+ options = append(options, WithDNSSearch(p.config.InfraContainer.DNSSearch))
+ }
+ if len(p.config.InfraContainer.DNSOption) > 0 {
+ options = append(options, WithDNSOption(p.config.InfraContainer.DNSOption))
+ }
+ if p.config.InfraContainer.UseImageHosts {
+ options = append(options, WithUseImageHosts())
+ }
+ if len(p.config.InfraContainer.HostAdd) > 0 {
+ options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
+ }
}
g.SetRootReadonly(true)
@@ -87,46 +126,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
}
containerName := p.ID()[:IDTruncLength] + "-infra"
- var options []CtrCreateOption
options = append(options, r.WithPod(p))
- options = append(options, WithRootFSFromImage(imgID, imgName, false))
+ options = append(options, WithRootFSFromImage(imgID, imgName))
options = append(options, WithName(containerName))
options = append(options, withIsInfra())
- // Since user namespace sharing is not implemented, we only need to check if it's rootless
- netmode := "bridge"
- if isRootless {
- netmode = "slirp4netns"
- }
- // PostConfigureNetNS should not be set since user namespace sharing is not implemented
- // and rootless networking no longer supports post configuration setup
- options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks))
-
- if p.config.InfraContainer.StaticIP != nil {
- options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
- }
- if p.config.InfraContainer.StaticMAC != nil {
- options = append(options, WithStaticMAC(p.config.InfraContainer.StaticMAC))
- }
- if p.config.InfraContainer.UseImageResolvConf {
- options = append(options, WithUseImageResolvConf())
- }
- if len(p.config.InfraContainer.DNSServer) > 0 {
- options = append(options, WithDNS(p.config.InfraContainer.DNSServer))
- }
- if len(p.config.InfraContainer.DNSSearch) > 0 {
- options = append(options, WithDNSSearch(p.config.InfraContainer.DNSSearch))
- }
- if len(p.config.InfraContainer.DNSOption) > 0 {
- options = append(options, WithDNSOption(p.config.InfraContainer.DNSOption))
- }
- if p.config.InfraContainer.UseImageHosts {
- options = append(options, WithUseImageHosts())
- }
- if len(p.config.InfraContainer.HostAdd) > 0 {
- options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
- }
-
return r.newContainer(ctx, g.Config, options...)
}
diff --git a/libpod/runtime_volume.go b/libpod/runtime_volume.go
index 835dccf9c..efc3c5bd9 100644
--- a/libpod/runtime_volume.go
+++ b/libpod/runtime_volume.go
@@ -36,9 +36,6 @@ func (r *Runtime) RemoveVolume(ctx context.Context, v *Volume, force bool) error
}
}
- v.lock.Lock()
- defer v.lock.Unlock()
-
return r.removeVolume(ctx, v, force)
}
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index 037cf4cc2..e9cfda9d4 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -124,6 +124,9 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
return define.ErrVolumeRemoved
}
+ v.lock.Lock()
+ defer v.lock.Unlock()
+
// Update volume status to pick up a potential removal from state
if err := v.update(); err != nil {
return err
diff --git a/libpod/util_test.go b/libpod/util_test.go
index 70e989e1a..227686c2b 100644
--- a/libpod/util_test.go
+++ b/libpod/util_test.go
@@ -1,8 +1,9 @@
package libpod
import (
- "github.com/stretchr/testify/assert"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestRemoveScientificNotationFromFloat(t *testing.T) {
diff --git a/libpod/volume.go b/libpod/volume.go
index 1ffed872e..70099d6f4 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -126,3 +126,10 @@ func (v *Volume) GID() int {
func (v *Volume) CreatedTime() time.Time {
return v.config.CreatedTime
}
+
+// Config returns the volume's configuration.
+func (v *Volume) Config() (*VolumeConfig, error) {
+ config := VolumeConfig{}
+ err := JSONDeepCopy(v.config, &config)
+ return &config, err
+}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index cada93829..08e19edb8 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -26,7 +26,7 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/adapter/shortcuts"
- "github.com/containers/libpod/pkg/systemdgen"
+ "github.com/containers/libpod/pkg/systemd/generate"
"github.com/containers/storage"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -338,7 +338,11 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *logs.LogOptions) er
if tailLen < 0 {
tailLen = 0
}
- logChannel := make(chan *logs.LogLine, tailLen*len(c.InputArgs)+1)
+ numContainers := len(c.InputArgs)
+ if numContainers == 0 {
+ numContainers = 1
+ }
+ logChannel := make(chan *logs.LogLine, tailLen*numContainers+1)
containers, err := shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
if err != nil {
return err
@@ -465,6 +469,10 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
logrus.Debugf("unable to remove container %s after failing to start and attach to it", ctr.ID())
}
}
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ logrus.Debugf("Deadlock error: %v", err)
+ return define.ExitCode(err), errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID())
+ }
return define.ExitCode(err), err
}
@@ -698,6 +706,11 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP
return exitCode, nil
}
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ logrus.Debugf("Deadlock error: %v", err)
+ return define.ExitCode(err), errors.Errorf("attempting to start container %s would cause a deadlock; please run 'podman system renumber' to resolve", ctr.ID())
+ }
+
if ctrRunning {
return 0, err
}
@@ -731,6 +744,10 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
+ if errors.Cause(err) == define.ErrWillDeadlock {
+ lastError = errors.Wrapf(err, "please run 'podman system renumber' to resolve deadlocks")
+ continue
+ }
lastError = errors.Wrapf(err, "unable to start container %q", container)
continue
}
@@ -1112,7 +1129,11 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
)
if !c.All {
- containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ names := []string{}
+ if len(c.InputArgs) >= 1 {
+ names = []string{c.InputArgs[0]}
+ }
+ containers, err = shortcuts.GetContainersByContext(false, c.Latest, names, r.Runtime)
} else {
containers, err = r.Runtime.GetRunningContainers()
}
@@ -1154,7 +1175,7 @@ func generateServiceName(c *cliconfig.GenerateSystemdValues, ctr *libpod.Contain
// generateSystemdgenContainerInfo is a helper to generate a
// systemdgen.ContainerInfo for `GenerateSystemd`.
-func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSystemdValues, nameOrID string, pod *libpod.Pod) (*systemdgen.ContainerInfo, bool, error) {
+func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSystemdValues, nameOrID string, pod *libpod.Pod) (*generate.ContainerInfo, bool, error) {
ctr, err := r.Runtime.LookupContainer(nameOrID)
if err != nil {
return nil, false, err
@@ -1172,7 +1193,7 @@ func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSyst
}
name, serviceName := generateServiceName(c, ctr, pod)
- info := &systemdgen.ContainerInfo{
+ info := &generate.ContainerInfo{
ServiceName: serviceName,
ContainerName: name,
RestartPolicy: c.RestartPolicy,
@@ -1187,7 +1208,7 @@ func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSyst
// GenerateSystemd creates a unit file for a container or pod.
func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
- opts := systemdgen.Options{
+ opts := generate.Options{
Files: c.Files,
New: c.New,
}
@@ -1196,7 +1217,7 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
if info, found, err := r.generateSystemdgenContainerInfo(c, c.InputArgs[0], nil); found && err != nil {
return "", err
} else if found && err == nil {
- return systemdgen.CreateContainerSystemdUnit(info, opts)
+ return generate.CreateContainerSystemdUnit(info, opts)
}
// --new does not support pods.
@@ -1242,7 +1263,7 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
// Traverse the dependency graph and create systemdgen.ContainerInfo's for
// each container.
- containerInfos := []*systemdgen.ContainerInfo{podInfo}
+ containerInfos := []*generate.ContainerInfo{podInfo}
for ctr, dependencies := range graph.DependencyMap() {
// Skip the infra container as we already generated it.
if ctr.ID() == infraID {
@@ -1272,7 +1293,7 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
if i > 0 {
builder.WriteByte('\n')
}
- out, err := systemdgen.CreateContainerSystemdUnit(info, opts)
+ out, err := generate.CreateContainerSystemdUnit(info, opts)
if err != nil {
return "", err
}
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index 49f086ef3..0d9fa7210 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -7,6 +7,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "net"
"os"
"path/filepath"
"strings"
@@ -248,6 +249,17 @@ func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateVa
err error
)
+ // This needs to be first, as a lot of options depend on
+ // WithInfraContainer()
+ if cli.Infra {
+ options = append(options, libpod.WithInfraContainer())
+ nsOptions, err := shared.GetNamespaceOptions(strings.Split(cli.Share, ","))
+ if err != nil {
+ return "", err
+ }
+ options = append(options, nsOptions...)
+ }
+
if cli.Flag("cgroup-parent").Changed {
options = append(options, libpod.WithPodCgroupParent(cli.CgroupParent))
}
@@ -264,17 +276,78 @@ func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateVa
options = append(options, libpod.WithPodHostname(cli.Hostname))
}
- if cli.Infra {
- options = append(options, libpod.WithInfraContainer())
- nsOptions, err := shared.GetNamespaceOptions(strings.Split(cli.Share, ","))
+ if cli.Flag("add-host").Changed {
+ options = append(options, libpod.WithPodHosts(cli.StringSlice("add-host")))
+ }
+ if cli.Flag("dns").Changed {
+ dns := cli.StringSlice("dns")
+ foundHost := false
+ for _, entry := range dns {
+ if entry == "host" {
+ foundHost = true
+ }
+ }
+ if foundHost && len(dns) > 1 {
+ return "", errors.Errorf("cannot set dns=host and still provide other DNS servers")
+ }
+ if foundHost {
+ options = append(options, libpod.WithPodUseImageResolvConf())
+ } else {
+ options = append(options, libpod.WithPodDNS(cli.StringSlice("dns")))
+ }
+ }
+ if cli.Flag("dns-opt").Changed {
+ options = append(options, libpod.WithPodDNSOption(cli.StringSlice("dns-opt")))
+ }
+ if cli.Flag("dns-search").Changed {
+ options = append(options, libpod.WithPodDNSSearch(cli.StringSlice("dns-search")))
+ }
+ if cli.Flag("ip").Changed {
+ ip := net.ParseIP(cli.String("ip"))
+ if ip == nil {
+ return "", errors.Errorf("invalid IP address %q passed to --ip", cli.String("ip"))
+ }
+
+ options = append(options, libpod.WithPodStaticIP(ip))
+ }
+ if cli.Flag("mac-address").Changed {
+ mac, err := net.ParseMAC(cli.String("mac-address"))
if err != nil {
- return "", err
+ return "", errors.Wrapf(err, "invalid MAC address %q passed to --mac-address", cli.String("mac-address"))
+ }
+
+ options = append(options, libpod.WithPodStaticMAC(mac))
+ }
+ if cli.Flag("network").Changed {
+ netValue := cli.String("network")
+ switch strings.ToLower(netValue) {
+ case "bridge":
+ // Do nothing.
+ // TODO: Maybe this should be split between slirp and
+ // bridge? Better to wait until someone asks...
+ logrus.Debugf("Pod using default network mode")
+ case "host":
+ logrus.Debugf("Pod will use host networking")
+ options = append(options, libpod.WithPodHostNetwork())
+ case "":
+ return "", errors.Errorf("invalid value passed to --net: must provide a comma-separated list of CNI networks or host")
+ default:
+ // We'll assume this is a comma-separated list of CNI
+ // networks.
+ networks := strings.Split(netValue, ",")
+ logrus.Debugf("Pod joining CNI networks: %v", networks)
+ options = append(options, libpod.WithPodNetworks(networks))
+ }
+ }
+ if cli.Flag("no-hosts").Changed {
+ if cli.Bool("no-hosts") {
+ options = append(options, libpod.WithPodUseImageHosts())
}
- options = append(options, nsOptions...)
}
- if len(cli.Publish) > 0 {
- portBindings, err := shared.CreatePortBindings(cli.Publish)
+ publish := cli.StringSlice("publish")
+ if len(publish) > 0 {
+ portBindings, err := shared.CreatePortBindings(publish)
if err != nil {
return "", err
}
@@ -497,6 +570,10 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa
}
podOptions = append(podOptions, libpod.WithPodHostname(hostname))
+ if podYAML.Spec.HostNetwork {
+ podOptions = append(podOptions, libpod.WithPodHostNetwork())
+ }
+
nsOptions, err := shared.GetNamespaceOptions(strings.Split(shared.DefaultKernelNamespaces, ","))
if err != nil {
return nil, err
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 5ef1a9216..20f089628 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -185,7 +185,7 @@ func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateVa
Infra: cli.Infra,
InfraCommand: cli.InfraCommand,
InfraImage: cli.InfraCommand,
- Publish: cli.Publish,
+ Publish: cli.StringSlice("publish"),
}
return iopodman.CreatePod().Call(r.Conn, pc)
diff --git a/pkg/api/handlers/decoder.go b/pkg/api/handlers/decoder.go
index 890d77ecc..03b86275d 100644
--- a/pkg/api/handlers/decoder.go
+++ b/pkg/api/handlers/decoder.go
@@ -3,8 +3,10 @@ package handlers
import (
"encoding/json"
"reflect"
+ "syscall"
"time"
+ "github.com/containers/libpod/pkg/util"
"github.com/gorilla/schema"
"github.com/sirupsen/logrus"
)
@@ -17,6 +19,9 @@ func NewAPIDecoder() *schema.Decoder {
d.IgnoreUnknownKeys(true)
d.RegisterConverter(map[string][]string{}, convertUrlValuesString)
d.RegisterConverter(time.Time{}, convertTimeString)
+
+ var Signal syscall.Signal
+ d.RegisterConverter(Signal, convertSignal)
return d
}
@@ -89,3 +94,11 @@ func convertTimeString(query string) reflect.Value {
func ParseDateTime(query string) time.Time {
return convertTimeString(query).Interface().(time.Time)
}
+
+func convertSignal(query string) reflect.Value {
+ signal, err := util.ParseSignal(query)
+ if err != nil {
+ logrus.Infof("convertSignal: Failed to parse %s: %s", query, err.Error())
+ }
+ return reflect.ValueOf(signal)
+}
diff --git a/pkg/api/handlers/containers_create.go b/pkg/api/handlers/generic/containers_create.go
index 48f0de94d..7e542752f 100644
--- a/pkg/api/handlers/containers_create.go
+++ b/pkg/api/handlers/generic/containers_create.go
@@ -1,4 +1,4 @@
-package handlers
+package generic
import (
"encoding/json"
@@ -6,10 +6,10 @@ import (
"net/http"
"strings"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
image2 "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/namespaces"
"github.com/containers/libpod/pkg/signal"
@@ -17,14 +17,13 @@ import (
"github.com/containers/storage"
"github.com/gorilla/schema"
"github.com/pkg/errors"
- log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
func CreateContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
- input := CreateContainerConfig{}
+ input := handlers.CreateContainerConfig{}
query := struct {
Name string `schema:"name"`
}{
@@ -52,34 +51,11 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()"))
return
}
-
cc.Name = query.Name
- var pod *libpod.Pod
- ctr, err := shared.CreateContainerFromCreateConfig(runtime, &cc, r.Context(), pod)
- if err != nil {
- if strings.Contains(err.Error(), "invalid log driver") {
- // this does not quite work yet and needs a little more massaging
- w.Header().Set("Content-Type", "text/plain; charset=us-ascii")
- w.WriteHeader(http.StatusInternalServerError)
- msg := fmt.Sprintf("logger: no log driver named '%s' is registered", input.HostConfig.LogConfig.Type)
- if _, err := fmt.Fprintln(w, msg); err != nil {
- log.Errorf("%s: %q", msg, err)
- }
- //s.WriteResponse(w, http.StatusInternalServerError, fmt.Sprintf("logger: no log driver named '%s' is registered", input.HostConfig.LogConfig.Type))
- return
- }
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "CreateContainerFromCreateConfig()"))
- return
- }
-
- response := ContainerCreateResponse{
- ID: ctr.ID(),
- Warnings: []string{}}
-
- utils.WriteResponse(w, http.StatusCreated, response)
+ utils.CreateContainer(r.Context(), w, runtime, &cc)
}
-func makeCreateConfig(input CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
+func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
var (
err error
init bool
diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go
index 19e2cc882..977979741 100644
--- a/pkg/api/handlers/generic/containers_stats.go
+++ b/pkg/api/handlers/generic/containers_stats.go
@@ -7,7 +7,6 @@ import (
"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/containers/libpod/pkg/cgroups"
docker "github.com/docker/docker/api/types"
@@ -58,17 +57,18 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
}
var preRead time.Time
- var preCPUStats docker.CPUStats
+ var preCPUStats CPUStats
if query.Stream {
preRead = time.Now()
systemUsage, _ := cgroups.GetSystemCPUUsage()
- preCPUStats = docker.CPUStats{
+ preCPUStats = CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: stats.CPUNano,
PercpuUsage: stats.PerCPU,
UsageInKernelmode: stats.CPUSystemNano,
UsageInUsermode: stats.CPUNano - stats.CPUSystemNano,
},
+ CPU: stats.CPU,
SystemUsage: systemUsage,
OnlineCPUs: 0,
ThrottlingData: docker.ThrottlingData{},
@@ -124,9 +124,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
}
systemUsage, _ := cgroups.GetSystemCPUUsage()
-
- s := handlers.Stats{StatsJSON: docker.StatsJSON{
- Stats: docker.Stats{
+ s := StatsJSON{
+ Stats: Stats{
Read: time.Now(),
PreRead: preRead,
PidsStats: docker.PidsStats{
@@ -143,13 +142,14 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
IoTimeRecursive: nil,
SectorsRecursive: nil,
},
- CPUStats: docker.CPUStats{
+ CPUStats: CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: cgroupStat.CPU.Usage.Total,
PercpuUsage: cgroupStat.CPU.Usage.PerCPU,
UsageInKernelmode: cgroupStat.CPU.Usage.Kernel,
UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel,
},
+ CPU: stats.CPU,
SystemUsage: systemUsage,
OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)),
ThrottlingData: docker.ThrottlingData{
@@ -173,7 +173,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
Name: stats.Name,
ID: stats.ContainerID,
Networks: net,
- }}
+ }
utils.WriteJSON(w, http.StatusOK, s)
if flusher, ok := w.(http.Flusher); ok {
diff --git a/pkg/api/handlers/generic/images.go b/pkg/api/handlers/generic/images.go
index c65db7575..1ced499d9 100644
--- a/pkg/api/handlers/generic/images.go
+++ b/pkg/api/handlers/generic/images.go
@@ -106,14 +106,14 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
query := struct {
- author string
- changes string
- comment string
- container string
+ Author string `schema:"author"`
+ Changes string `schema:"changes"`
+ Comment string `schema:"comment"`
+ Container string `schema:"container"`
//fromSrc string # fromSrc is currently unused
- pause bool
- repo string
- tag string
+ Pause bool `schema:"pause"`
+ Repo string `schema:"repo"`
+ Tag string `schema:"tag"`
}{
// This is where you can override the golang default value for one of fields
}
@@ -145,22 +145,22 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
return
}
- if len(query.tag) > 0 {
- tag = query.tag
+ if len(query.Tag) > 0 {
+ tag = query.Tag
}
- options.Message = query.comment
- options.Author = query.author
- options.Pause = query.pause
- options.Changes = strings.Fields(query.changes)
- ctr, err := runtime.LookupContainer(query.container)
+ options.Message = query.Comment
+ options.Author = query.Author
+ options.Pause = query.Pause
+ options.Changes = strings.Fields(query.Changes)
+ ctr, err := runtime.LookupContainer(query.Container)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
return
}
// I know mitr hates this ... but doing for now
- if len(query.repo) > 1 {
- destImage = fmt.Sprintf("%s:%s", query.repo, tag)
+ if len(query.Repo) > 1 {
+ destImage = fmt.Sprintf("%s:%s", query.Repo, tag)
}
commitImage, err := ctr.Commit(r.Context(), destImage, options)
@@ -179,8 +179,8 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
query := struct {
- fromSrc string
- changes []string
+ FromSrc string `schema:"fromSrc"`
+ Changes []string `schema:"changes"`
}{
// This is where you can override the golang default value for one of fields
}
@@ -190,7 +190,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
return
}
// fromSrc – Source to import. The value may be a URL from which the image can be retrieved or - to read the image from the request body. This parameter may only be used when importing an image.
- source := query.fromSrc
+ source := query.FromSrc
if source == "-" {
f, err := ioutil.TempFile("", "api_load.tar")
if err != nil {
@@ -202,7 +202,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
}
}
- iid, err := runtime.Import(r.Context(), source, "", query.changes, "", false)
+ iid, err := runtime.Import(r.Context(), source, "", query.Changes, "", false)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
return
@@ -238,8 +238,8 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
query := struct {
- fromImage string
- tag string
+ FromImage string `schema:"fromImage"`
+ Tag string `schema:"tag"`
}{
// This is where you can override the golang default value for one of fields
}
@@ -254,9 +254,9 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
repo – Repository name given to an image when it is imported. The repo may include a tag. This parameter may only be used when importing an image.
tag – Tag or digest. If empty when pulling an image, this causes all tags for the given image to be pulled.
*/
- fromImage := query.fromImage
- if len(query.tag) < 1 {
- fromImage = fmt.Sprintf("%s:%s", fromImage, query.tag)
+ fromImage := query.FromImage
+ if len(query.Tag) >= 1 {
+ fromImage = fmt.Sprintf("%s:%s", fromImage, query.Tag)
}
// TODO
diff --git a/pkg/api/handlers/generic/swagger.go b/pkg/api/handlers/generic/swagger.go
index bfe527c41..c9c9610bb 100644
--- a/pkg/api/handlers/generic/swagger.go
+++ b/pkg/api/handlers/generic/swagger.go
@@ -1,13 +1,15 @@
package generic
-import "github.com/containers/libpod/pkg/api/handlers"
+import (
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+)
// Create container
// swagger:response ContainerCreateResponse
type swagCtrCreateResponse struct {
// in:body
Body struct {
- handlers.ContainerCreateResponse
+ utils.ContainerCreateResponse
}
}
diff --git a/pkg/api/handlers/generic/types.go b/pkg/api/handlers/generic/types.go
new file mode 100644
index 000000000..f068ac011
--- /dev/null
+++ b/pkg/api/handlers/generic/types.go
@@ -0,0 +1,55 @@
+package generic
+
+import (
+ "time"
+
+ docker "github.com/docker/docker/api/types"
+)
+
+// CPUStats aggregates and wraps all CPU related info of container
+type CPUStats struct {
+ // CPU Usage. Linux and Windows.
+ CPUUsage docker.CPUUsage `json:"cpu_usage"`
+
+ // System Usage. Linux only.
+ SystemUsage uint64 `json:"system_cpu_usage,omitempty"`
+
+ // Online CPUs. Linux only.
+ OnlineCPUs uint32 `json:"online_cpus,omitempty"`
+
+ // Usage of CPU in %. Linux only.
+ CPU float64 `json:"cpu"`
+
+ // Throttling Data. Linux only.
+ ThrottlingData docker.ThrottlingData `json:"throttling_data,omitempty"`
+}
+
+// Stats is Ultimate struct aggregating all types of stats of one container
+type Stats struct {
+ // Common stats
+ Read time.Time `json:"read"`
+ PreRead time.Time `json:"preread"`
+
+ // Linux specific stats, not populated on Windows.
+ PidsStats docker.PidsStats `json:"pids_stats,omitempty"`
+ BlkioStats docker.BlkioStats `json:"blkio_stats,omitempty"`
+
+ // Windows specific stats, not populated on Linux.
+ NumProcs uint32 `json:"num_procs"`
+ StorageStats docker.StorageStats `json:"storage_stats,omitempty"`
+
+ // Shared stats
+ CPUStats CPUStats `json:"cpu_stats,omitempty"`
+ PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous"
+ MemoryStats docker.MemoryStats `json:"memory_stats,omitempty"`
+}
+
+type StatsJSON struct {
+ Stats
+
+ Name string `json:"name,omitempty"`
+ ID string `json:"id,omitempty"`
+
+ // Networks request version >=1.21
+ Networks map[string]docker.NetworkStats `json:"networks,omitempty"`
+}
diff --git a/pkg/api/handlers/images.go b/pkg/api/handlers/images.go
index cd3c0b93f..2086ce748 100644
--- a/pkg/api/handlers/images.go
+++ b/pkg/api/handlers/images.go
@@ -7,6 +7,7 @@ import (
"os"
"strconv"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/api/handlers/utils"
@@ -147,15 +148,42 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
return
}
- // TODO filters are a bit undefined here in terms of what exactly the input looks
- // like. We need to understand that a bit more.
+
+ filter := image.SearchFilter{}
+ if len(query.Filters) > 0 {
+ if len(query.Filters["stars"]) > 0 {
+ stars, err := strconv.Atoi(query.Filters["stars"][0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filter.Stars = stars
+ }
+ if len(query.Filters["is-official"]) > 0 {
+ isOfficial, err := strconv.ParseBool(query.Filters["is-official"][0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filter.IsOfficial = types.NewOptionalBool(isOfficial)
+ }
+ if len(query.Filters["is-automated"]) > 0 {
+ isAutomated, err := strconv.ParseBool(query.Filters["is-automated"][0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filter.IsAutomated = types.NewOptionalBool(isAutomated)
+ }
+ }
options := image.SearchOptions{
- Filter: image.SearchFilter{},
+ Filter: filter,
Limit: query.Limit,
}
results, err := image.SearchImages(query.Term, options)
if err != nil {
- utils.InternalServerError(w, err)
+ utils.BadRequest(w, "term", query.Term, err)
+ return
}
utils.WriteResponse(w, http.StatusOK, results)
}
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
new file mode 100644
index 000000000..ebca41151
--- /dev/null
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -0,0 +1,29 @@
+package libpod
+
+import (
+ "encoding/json"
+ "net/http"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/specgen"
+ "github.com/pkg/errors"
+)
+
+// CreateContainer takes a specgenerator and makes a container. It returns
+// the new container ID on success along with any warnings.
+func CreateContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ var sg specgen.SpecGenerator
+ if err := json.NewDecoder(r.Body).Decode(&sg); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ return
+ }
+ ctr, err := sg.MakeContainer(runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ response := utils.ContainerCreateResponse{ID: ctr.ID()}
+ utils.WriteJSON(w, http.StatusCreated, response)
+}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index eac0e4dad..71603e6cc 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -8,6 +8,7 @@ import (
"net/http"
"os"
"strconv"
+ "strings"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
@@ -133,11 +134,16 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
var libpodFilters = []string{}
if _, found := r.URL.Query()["filters"]; found {
- all, err = strconv.ParseBool(query.Filters["all"][0])
- if err != nil {
- utils.InternalServerError(w, err)
- return
+ dangling := query.Filters["all"]
+ if len(dangling) > 0 {
+ all, err = strconv.ParseBool(query.Filters["all"][0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
}
+ // dangling is special and not implemented in the libpod side of things
+ delete(query.Filters, "dangling")
for k, v := range query.Filters {
libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", k, v[0]))
}
@@ -157,7 +163,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
Compress bool `schema:"compress"`
Format string `schema:"format"`
}{
- // override any golang type defaults
+ Format: "docker-archive",
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
@@ -166,11 +172,6 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
return
}
- if len(query.Format) < 1 {
- utils.InternalServerError(w, errors.New("format parameter cannot be empty."))
- return
- }
-
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
@@ -186,6 +187,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.ImageNotFound(w, name, err)
return
}
+
if err := newImage.Save(r.Context(), name, query.Format, tmpfile.Name(), []string{}, false, query.Compress); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
@@ -234,8 +236,20 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
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}})
+ split := strings.Split(loadedImage, ",")
+ newImage, err := runtime.ImageRuntime().NewFromLocal(split[0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ // TODO this should go into libpod proper at some point.
+ if len(query.Reference) > 0 {
+ if err := newImage.TagImage(query.Reference); err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ }
+ utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesLoadReport{ID: loadedImage})
}
func ImagesImport(w http.ResponseWriter, r *http.Request) {
@@ -275,7 +289,6 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
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"))
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index d043b1204..f5700579b 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -99,12 +99,10 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http_code, err)
return
}
- utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.CgroupParent()})
+ utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()})
}
func Pods(w http.ResponseWriter, r *http.Request) {
- // 200 ok
- // 500 internal
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
podInspectData []*libpod.PodInspect
@@ -121,7 +119,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
return
}
- if _, found := r.URL.Query()["filters"]; found {
+ if len(query.Filters) > 0 {
utils.Error(w, "filters are not implemented yet", http.StatusInternalServerError, define.ErrNotImplemented)
return
}
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index 7e7e46718..9b10ee890 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -3,9 +3,11 @@ package libpod
import (
"encoding/json"
"net/http"
+ "strings"
"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"
@@ -29,7 +31,6 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
return
}
-
// decode params from body
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
@@ -49,14 +50,21 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
parsedOptions, err := shared.ParseVolumeOptions(input.Opts)
if err != nil {
utils.InternalServerError(w, err)
+ return
}
volumeOptions = append(volumeOptions, parsedOptions...)
}
vol, err := runtime.NewVolume(r.Context(), volumeOptions...)
if err != nil {
utils.InternalServerError(w, err)
+ return
+ }
+ config, err := vol.Config()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
}
- utils.WriteResponse(w, http.StatusOK, vol.Name())
+ utils.WriteResponse(w, http.StatusOK, config)
}
func InspectVolume(w http.ResponseWriter, r *http.Request) {
@@ -76,25 +84,46 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
}
func ListVolumes(w http.ResponseWriter, r *http.Request) {
- //var (
- // runtime = r.Context().Value("runtime").(*libpod.Runtime)
- // decoder = r.Context().Value("decoder").(*schema.Decoder)
- //)
- //query := struct {
- // Filter string `json:"filter"`
- //}{
- // // override any golang type defaults
- //}
- //
- //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
- //}
- /*
- This is all in main in cmd and needs to be extracted from there first.
- */
+ var (
+ decoder = r.Context().Value("decoder").(*schema.Decoder)
+ err error
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ volumeConfigs []*libpod.VolumeConfig
+ volumeFilters []libpod.VolumeFilter
+ )
+ query := struct {
+ Filters map[string][]string `schema:"filters"`
+ }{
+ // override any golang type defaults
+ }
+
+ 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.Filters) > 0 {
+ volumeFilters, err = generateVolumeFilters(query.Filters)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ }
+ vols, err := runtime.Volumes(volumeFilters...)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ for _, v := range vols {
+ config, err := v.Config()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ volumeConfigs = append(volumeConfigs, config)
+ }
+ utils.WriteResponse(w, http.StatusOK, volumeConfigs)
}
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
@@ -133,9 +162,77 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
vol, err := runtime.LookupVolume(name)
if err != nil {
utils.VolumeNotFound(w, name, err)
+ return
}
if err := runtime.RemoveVolume(r.Context(), vol, query.Force); err != nil {
+ if errors.Cause(err) == define.ErrVolumeBeingUsed {
+ utils.Error(w, "volumes being used", http.StatusConflict, err)
+ return
+ }
utils.InternalServerError(w, err)
+ return
}
utils.WriteResponse(w, http.StatusNoContent, "")
}
+
+func generateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter, error) {
+ var vf []libpod.VolumeFilter
+ for filter, v := range filters {
+ for _, val := range v {
+ switch filter {
+ case "name":
+ nameVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return nameVal == v.Name()
+ })
+ case "driver":
+ driverVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Driver() == driverVal
+ })
+ case "scope":
+ scopeVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Scope() == scopeVal
+ })
+ case "label":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Labels() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ case "opt":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Options() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ default:
+ return nil, errors.Errorf("%q is in an invalid volume filter", filter)
+ }
+ }
+ }
+ return vf, nil
+}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index f5d9f9ad5..2930a9567 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -78,10 +78,6 @@ type Container struct {
docker.ContainerCreateConfig
}
-type ContainerStats struct {
- docker.ContainerStats
-}
-
type Version struct {
docker.Version
}
@@ -132,25 +128,27 @@ type CreateContainerConfig struct {
NetworkingConfig dockerNetwork.NetworkingConfig
}
+// swagger:model VolumeCreate
type VolumeCreateConfig struct {
- Name string `json:"name"`
- Driver string `schema:"driver"`
- Label map[string]string `schema:"label"`
- Opts map[string]string `schema:"opts"`
+ // New volume's name. Can be left blank
+ Name string `schema:"name"`
+ // Volume driver to use
+ Driver string `schema:"driver"`
+ // User-defined key/value metadata.
+ Label map[string]string `schema:"label"`
+ // Mapping of driver options and values.
+ Opts map[string]string `schema:"opts"`
}
type IDResponse struct {
ID string `json:"id"`
}
-type Stats struct {
- docker.StatsJSON
-}
-
type ContainerTopOKBody struct {
dockerContainer.ContainerTopOKBody
}
+// swagger:model PodCreateConfig
type PodCreateConfig struct {
Name string `json:"name"`
CGroupParent string `json:"cgroup-parent"`
@@ -351,18 +349,21 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
func LibpodToContainer(l *libpod.Container, infoData []define.InfoData) (*Container, error) {
imageId, imageName := l.Image()
- sizeRW, err := l.RWSize()
- if err != nil {
+
+ var (
+ err error
+ sizeRootFs int64
+ sizeRW int64
+ state define.ContainerStatus
+ )
+
+ if state, err = l.State(); err != nil {
return nil, err
}
-
- SizeRootFs, err := l.RootFsSize()
- if err != nil {
+ if sizeRW, err = l.RWSize(); err != nil {
return nil, err
}
-
- state, err := l.State()
- if err != nil {
+ if sizeRootFs, err = l.RootFsSize(); err != nil {
return nil, err
}
@@ -375,7 +376,7 @@ func LibpodToContainer(l *libpod.Container, infoData []define.InfoData) (*Contai
Created: l.CreatedTime().Unix(),
Ports: nil,
SizeRw: sizeRW,
- SizeRootFs: SizeRootFs,
+ SizeRootFs: sizeRootFs,
Labels: l.Labels(),
State: string(state),
Status: "",
@@ -545,11 +546,3 @@ func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) {
}
return ports, nil
}
-
-// ContainerCreateResponse is the response struct for creating a container
-type ContainerCreateResponse struct {
- // ID of the container created
- ID string `json:"id"`
- // Warnings during container creation
- Warnings []string `json:"Warnings"`
-}
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index 74485edf2..402005581 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -1,6 +1,7 @@
package utils
import (
+ "context"
"fmt"
"net/http"
"syscall"
@@ -9,13 +10,22 @@ import (
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ createconfig "github.com/containers/libpod/pkg/spec"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
+// ContainerCreateResponse is the response struct for creating a container
+type ContainerCreateResponse struct {
+ // ID of the container created
+ ID string `json:"id"`
+ // Warnings during container creation
+ Warnings []string `json:"Warnings"`
+}
+
func KillContainer(w http.ResponseWriter, r *http.Request) (*libpod.Container, error) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decorder").(*schema.Decoder)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Signal syscall.Signal `schema:"signal"`
}{
@@ -119,3 +129,18 @@ func GenerateFilterFuncsFromMap(r *libpod.Runtime, filters map[string][]string)
}
return filterFuncs, nil
}
+
+func CreateContainer(ctx context.Context, w http.ResponseWriter, runtime *libpod.Runtime, cc *createconfig.CreateConfig) {
+ var pod *libpod.Pod
+ ctr, err := shared.CreateContainerFromCreateConfig(runtime, cc, ctx, pod)
+ if err != nil {
+ Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "CreateContainerFromCreateConfig()"))
+ return
+ }
+
+ response := ContainerCreateResponse{
+ ID: ctr.ID(),
+ Warnings: []string{}}
+
+ WriteResponse(w, http.StatusCreated, response)
+}
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index d0dfbf3ab..f68a71561 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -31,12 +31,16 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) {
if _, found := mux.Vars(r)["digests"]; found && query.Digests {
UnSupportedParameter("digests")
}
+
if len(query.Filters) > 0 {
for k, v := range query.Filters {
for _, val := range v {
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
}
}
+ return runtime.ImageRuntime().GetImagesWithFilters(filters)
+ } else {
+ return runtime.ImageRuntime().GetImages()
}
- return runtime.ImageRuntime().GetImagesWithFilters(filters)
+
}
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index 4b93998ee..30a1680c9 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -2,32 +2,52 @@ package server
import (
"context"
+ "fmt"
"net/http"
+ "runtime"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
log "github.com/sirupsen/logrus"
)
// APIHandler is a wrapper to enhance HandlerFunc's and remove redundant code
-func APIHandler(ctx context.Context, h http.HandlerFunc) http.HandlerFunc {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Debugf("APIHandler -- Method: %s URL: %s", r.Method, r.URL.String())
- if err := r.ParseForm(); err != nil {
- log.Infof("Failed Request: unable to parse form: %q", err)
- }
+func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ // http.Server hides panics, we want to see them and fix the cause.
+ defer func() {
+ err := recover()
+ if err != nil {
+ buf := make([]byte, 1<<20)
+ n := runtime.Stack(buf, true)
+ log.Warnf("Recovering from podman handler panic: %v, %s", err, buf[:n])
+ // Try to inform client things went south... won't work if handler already started writing response body
+ utils.InternalServerError(w, fmt.Errorf("%v", err))
+ }
+ }()
+
+ // Wrapper to hide some boiler plate
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ // Connection counting, ugh. Needed to support the sliding window for idle checking.
+ s.ConnectionCh <- EnterHandler
+ defer func() { s.ConnectionCh <- ExitHandler }()
+
+ log.Debugf("APIHandler -- Method: %s URL: %s (conn %d/%d)",
+ r.Method, r.URL.String(), s.ActiveConnections, s.TotalConnections)
- // TODO: Use ConnContext when ported to go 1.13
- c := context.WithValue(r.Context(), "decoder", ctx.Value("decoder"))
- c = context.WithValue(c, "runtime", ctx.Value("runtime"))
- c = context.WithValue(c, "shutdownFunc", ctx.Value("shutdownFunc"))
- r = r.WithContext(c)
+ if err := r.ParseForm(); err != nil {
+ log.Infof("Failed Request: unable to parse form: %q", err)
+ }
- h(w, r)
+ // TODO: Use r.ConnContext when ported to go 1.13
+ c := context.WithValue(r.Context(), "decoder", s.Decoder)
+ c = context.WithValue(c, "runtime", s.Runtime)
+ c = context.WithValue(c, "shutdownFunc", s.Shutdown)
+ r = r.WithContext(c)
- shutdownFunc := r.Context().Value("shutdownFunc").(func() error)
- if err := shutdownFunc(); err != nil {
- log.Errorf("Failed to shutdown Server in APIHandler(): %s", err.Error())
+ h(w, r)
}
- })
+ fn(w, r)
+ }
}
// VersionedPath prepends the version parsing code
diff --git a/pkg/api/server/register_auth.go b/pkg/api/server/register_auth.go
index 9f312683d..8db131153 100644
--- a/pkg/api/server/register_auth.go
+++ b/pkg/api/server/register_auth.go
@@ -5,7 +5,7 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterAuthHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/auth"), APIHandler(s.Context, handlers.UnsupportedHandler))
+func (s *APIServer) registerAuthHandlers(r *mux.Router) error {
+ r.Handle(VersionedPath("/auth"), s.APIHandler(handlers.UnsupportedHandler))
return nil
}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index b1facc27c..6a2ba4b1e 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -9,8 +9,8 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
- // swagger:operation POST /containers/create compat containerCreate
+func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
+ // swagger:operation POST /containers/create compat createContainer
// ---
// summary: Create a container
// tags:
@@ -33,7 +33,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, handlers.CreateContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/create"), s.APIHandler(generic.CreateContainer)).Methods(http.MethodPost)
// swagger:operation GET /containers/json compat listContainers
// ---
// tags:
@@ -83,7 +83,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/json"), APIHandler(s.Context, generic.ListContainers)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/json"), s.APIHandler(generic.ListContainers)).Methods(http.MethodGet)
// swagger:operation POST /containers/prune compat pruneContainers
// ---
// tags:
@@ -105,7 +105,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/DocsContainerPruneReport"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/prune"), APIHandler(s.Context, handlers.PruneContainers)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/prune"), s.APIHandler(handlers.PruneContainers)).Methods(http.MethodPost)
// swagger:operation DELETE /containers/{name} compat removeContainer
// ---
// tags:
@@ -144,7 +144,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}"), APIHandler(s.Context, generic.RemoveContainer)).Methods(http.MethodDelete)
+ r.HandleFunc(VersionedPath("/containers/{name}"), s.APIHandler(generic.RemoveContainer)).Methods(http.MethodDelete)
// swagger:operation GET /containers/{name}/json compat getContainer
// ---
// tags:
@@ -171,8 +171,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/json"), APIHandler(s.Context, generic.GetContainer)).Methods(http.MethodGet)
- // swagger:operation post /containers/{name}/kill compat killcontainer
+ r.HandleFunc(VersionedPath("/containers/{name}/json"), s.APIHandler(generic.GetContainer)).Methods(http.MethodGet)
+ // swagger:operation POST /containers/{name}/kill compat killContainer
// ---
// tags:
// - containers (compat)
@@ -201,8 +201,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/kill"), APIHandler(s.Context, generic.KillContainer)).Methods(http.MethodPost)
- // swagger:operation GET /containers/{name}/logs compat LogsFromContainer
+ r.HandleFunc(VersionedPath("/containers/{name}/kill"), s.APIHandler(generic.KillContainer)).Methods(http.MethodPost)
+ // swagger:operation GET /containers/{name}/logs compat logsFromContainer
// ---
// tags:
// - containers (compat)
@@ -253,7 +253,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/logs"), APIHandler(s.Context, generic.LogsFromContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/{name}/logs"), s.APIHandler(generic.LogsFromContainer)).Methods(http.MethodGet)
// swagger:operation POST /containers/{name}/pause compat pauseContainer
// ---
// tags:
@@ -275,8 +275,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost)
- r.HandleFunc(VersionedPath("/containers/{name}/rename"), APIHandler(s.Context, handlers.UnsupportedHandler)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/pause"), s.APIHandler(handlers.PauseContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/rename"), s.APIHandler(handlers.UnsupportedHandler)).Methods(http.MethodPost)
// swagger:operation POST /containers/{name}/restart compat restartContainer
// ---
// tags:
@@ -301,7 +301,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/restart"), s.APIHandler(handlers.RestartContainer)).Methods(http.MethodPost)
// swagger:operation POST /containers/{name}/start compat startContainer
// ---
// tags:
@@ -329,7 +329,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/start"), s.APIHandler(handlers.StartContainer)).Methods(http.MethodPost)
// swagger:operation GET /containers/{name}/stats compat statsContainer
// ---
// tags:
@@ -356,7 +356,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/{name}/stats"), s.APIHandler(generic.StatsContainer)).Methods(http.MethodGet)
// swagger:operation POST /containers/{name}/stop compat stopContainer
// ---
// tags:
@@ -384,7 +384,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/stop"), s.APIHandler(handlers.StopContainer)).Methods(http.MethodPost)
// swagger:operation GET /containers/{name}/top compat topContainer
// ---
// tags:
@@ -409,7 +409,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/{name}/top"), s.APIHandler(handlers.TopContainer)).Methods(http.MethodGet)
// swagger:operation POST /containers/{name}/unpause compat unpauseContainer
// ---
// tags:
@@ -431,7 +431,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/unpause"), s.APIHandler(handlers.UnpauseContainer)).Methods(http.MethodPost)
// swagger:operation POST /containers/{name}/wait compat waitContainer
// ---
// tags:
@@ -457,8 +457,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/wait"), APIHandler(s.Context, generic.WaitContainer)).Methods(http.MethodPost)
- // swagger:operation POST /containers/{name}/attach compat attach
+ r.HandleFunc(VersionedPath("/containers/{name}/wait"), s.APIHandler(generic.WaitContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /containers/{name}/attach compat attachContainer
// ---
// tags:
// - containers (compat)
@@ -512,8 +512,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost)
- // swagger:operation POST /containers/{name}/resize compat resize
+ r.HandleFunc(VersionedPath("/containers/{name}/attach"), s.APIHandler(handlers.AttachContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /containers/{name}/resize compat resizeContainer
// ---
// tags:
// - containers (compat)
@@ -544,13 +544,37 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/containers/{name}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/containers/{name}/resize"), s.APIHandler(handlers.ResizeContainer)).Methods(http.MethodPost)
/*
libpod endpoints
*/
- r.HandleFunc(VersionedPath("/libpod/containers/create"), APIHandler(s.Context, handlers.CreateContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/create libpod libpodCreateContainer
+ // ---
+ // summary: Create a container
+ // tags:
+ // - containers
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: body
+ // name: create
+ // description: attributes for creating a container
+ // schema:
+ // $ref: "#/definitions/SpecGenerator"
+ // responses:
+ // 201:
+ // $ref: "#/responses/ContainerCreateResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/create"), s.APIHandler(libpod.CreateContainer)).Methods(http.MethodPost)
// swagger:operation GET /libpod/containers/json libpod libpodListContainers
// ---
// tags:
@@ -591,21 +615,21 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// name: filters
// type: string
// description: |
- // Returns a list of containers.
- // - ancestor=(<image-name>[:<tag>], <image id>, or <image@digest>)
- // - before=(<container id> or <container name>)
- // - expose=(<port>[/<proto>]|<startport-endport>/[<proto>])
- // - exited=<int> containers with exit code of <int>
- // - health=(starting|healthy|unhealthy|none)
- // - id=<ID> a container's ID
- // - is-task=(true|false)
- // - label=key or label="key=value" of a container label
- // - name=<name> a container's name
- // - network=(<network id> or <network name>)
- // - publish=(<port>[/<proto>]|<startport-endport>/[<proto>])
- // - since=(<container id> or <container name>)
- // - status=(created|restarting|running|removing|paused|exited|dead)
- // - volume=(<volume name> or <mount point destination>)
+ // A JSON encoded value of the filters (a `map[string][]string`) to process on the containers list. Available filters:
+ // - `ancestor`=(`<image-name>[:<tag>]`, `<image id>`, or `<image@digest>`)
+ // - `before`=(`<container id>` or `<container name>`)
+ // - `expose`=(`<port>[/<proto>]` or `<startport-endport>/[<proto>]`)
+ // - `exited=<int>` containers with exit code of `<int>`
+ // - `health`=(`starting`, `healthy`, `unhealthy` or `none`)
+ // - `id=<ID>` a container's ID
+ // - `is-task`=(`true` or `false`)
+ // - `label`=(`key` or `"key=value"`) of an container label
+ // - `name=<name>` a container's name
+ // - `network`=(`<network id>` or `<network name>`)
+ // - `publish`=(`<port>[/<proto>]` or `<startport-endport>/[<proto>]`)
+ // - `since`=(`<container id>` or `<container name>`)
+ // - `status`=(`created`, `restarting`, `running`, `removing`, `paused`, `exited` or `dead`)
+ // - `volume`=(`<volume name>` or `<mount point destination>`)
// produces:
// - application/json
// responses:
@@ -615,7 +639,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/json"), APIHandler(s.Context, libpod.ListContainers)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/json"), s.APIHandler(libpod.ListContainers)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/prune libpod libpodPruneContainers
// ---
// tags:
@@ -637,8 +661,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/DocsLibpodPruneResponse"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/prune"), APIHandler(s.Context, handlers.PruneContainers)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/containers/showmounted libpod showMounterContainers
+ r.HandleFunc(VersionedPath("/libpod/containers/prune"), s.APIHandler(handlers.PruneContainers)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/containers/showmounted libpod libpodShowMountedContainers
// ---
// tags:
// - containers
@@ -655,7 +679,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// type: string
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/showmounted"), APIHandler(s.Context, libpod.ShowMountedContainers)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/showmounted"), s.APIHandler(libpod.ShowMountedContainers)).Methods(http.MethodGet)
// swagger:operation DELETE /libpod/containers/{name} libpod libpodRemoveContainer
// ---
// tags:
@@ -689,7 +713,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}"), APIHandler(s.Context, libpod.RemoveContainer)).Methods(http.MethodDelete)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}"), s.APIHandler(libpod.RemoveContainer)).Methods(http.MethodDelete)
// swagger:operation GET /libpod/containers/{name}/json libpod libpodGetContainer
// ---
// tags:
@@ -715,7 +739,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/json"), APIHandler(s.Context, libpod.GetContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/json"), s.APIHandler(libpod.GetContainer)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{name}/kill libpod libpodKillContainer
// ---
// tags:
@@ -744,8 +768,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/kill"), APIHandler(s.Context, libpod.KillContainer)).Methods(http.MethodGet)
- // swagger:operation GET /libpod/containers/{name}/mount libpod mountContainer
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/kill"), s.APIHandler(libpod.KillContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/{name}/mount libpod libpodMountContainer
// ---
// tags:
// - containers
@@ -770,7 +794,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/mount"), APIHandler(s.Context, libpod.MountContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/mount"), s.APIHandler(libpod.MountContainer)).Methods(http.MethodPost)
// swagger:operation POST /libpod/containers/{name}/unmount libpod libpodUnmountContainer
// ---
// tags:
@@ -792,7 +816,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/unmount"), APIHandler(s.Context, libpod.UnmountContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/unmount"), s.APIHandler(libpod.UnmountContainer)).Methods(http.MethodPost)
// swagger:operation GET /libpod/containers/{name}/logs libpod libpodLogsFromContainer
// ---
// tags:
@@ -844,7 +868,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/logs"), APIHandler(s.Context, generic.LogsFromContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/logs"), s.APIHandler(generic.LogsFromContainer)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{name}/pause libpod libpodPauseContainer
// ---
// tags:
@@ -866,7 +890,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// "$ref": "#/responses/NoSuchContainer"
// 500:
// "$ref": "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), APIHandler(s.Context, handlers.PauseContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name:..*}/pause"), s.APIHandler(handlers.PauseContainer)).Methods(http.MethodPost)
// swagger:operation POST /libpod/containers/{name}/restart libpod libpodRestartContainer
// ---
// tags:
@@ -891,7 +915,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/restart"), APIHandler(s.Context, handlers.RestartContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/restart"), s.APIHandler(handlers.RestartContainer)).Methods(http.MethodPost)
// swagger:operation POST /libpod/containers/{name}/start libpod libpodStartContainer
// ---
// tags:
@@ -919,7 +943,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/start"), APIHandler(s.Context, handlers.StartContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/start"), s.APIHandler(handlers.StartContainer)).Methods(http.MethodPost)
// swagger:operation GET /libpod/containers/{name}/stats libpod libpodStatsContainer
// ---
// tags:
@@ -946,7 +970,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), APIHandler(s.Context, generic.StatsContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), s.APIHandler(generic.StatsContainer)).Methods(http.MethodGet)
// swagger:operation GET /libpod/containers/{name}/top libpod libpodTopContainer
// ---
// tags:
@@ -980,7 +1004,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/top"), APIHandler(s.Context, handlers.TopContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/top"), s.APIHandler(handlers.TopContainer)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{name}/unpause libpod libpodUnpauseContainer
// ---
// tags:
@@ -1001,7 +1025,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/unpause"), APIHandler(s.Context, handlers.UnpauseContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/unpause"), s.APIHandler(handlers.UnpauseContainer)).Methods(http.MethodPost)
// swagger:operation POST /libpod/containers/{name}/wait libpod libpodWaitContainer
// ---
// tags:
@@ -1022,8 +1046,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/wait"), APIHandler(s.Context, libpod.WaitContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{name}/exists libpod containerExists
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/wait"), s.APIHandler(libpod.WaitContainer)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/containers/{name}/exists libpod libpodContainerExists
// ---
// tags:
// - containers
@@ -1044,7 +1068,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/exists"), APIHandler(s.Context, libpod.ContainerExists)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/exists"), s.APIHandler(libpod.ContainerExists)).Methods(http.MethodGet)
// swagger:operation POST /libpod/containers/{name}/stop libpod libpodStopContainer
// ---
// tags:
@@ -1071,8 +1095,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/stop"), APIHandler(s.Context, handlers.StopContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{name}/attach libpod libpodAttach
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/stop"), s.APIHandler(handlers.StopContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/{name}/attach libpod libpodAttachContainer
// ---
// tags:
// - containers
@@ -1126,8 +1150,8 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/attach"), APIHandler(s.Context, handlers.AttachContainer)).Methods(http.MethodPost)
- // swagger:operation POST /libpod/containers/{name}/resize libpod libpodResize
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/attach"), s.APIHandler(handlers.AttachContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/containers/{name}/resize libpod libpodResizeContainer
// ---
// tags:
// - containers
@@ -1158,6 +1182,6 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchContainer"
// 500:
// $ref: "#/responses/InternalError"
- r.HandleFunc(VersionedPath("/libpod/containers/{name}/resize"), APIHandler(s.Context, handlers.ResizeContainer)).Methods(http.MethodPost)
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/resize"), s.APIHandler(handlers.ResizeContainer)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/register_distribution.go b/pkg/api/server/register_distribution.go
index b0ac61fb8..f03662224 100644
--- a/pkg/api/server/register_distribution.go
+++ b/pkg/api/server/register_distribution.go
@@ -5,7 +5,7 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterDistributionHandlers(r *mux.Router) error {
+func (s *APIServer) registerDistributionHandlers(r *mux.Router) error {
r.HandleFunc(VersionedPath("/distribution/{name}/json"), handlers.UnsupportedHandler)
return nil
}
diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go
index 090f66323..bc3b62662 100644
--- a/pkg/api/server/register_events.go
+++ b/pkg/api/server/register_events.go
@@ -1,11 +1,13 @@
package server
import (
+ "net/http"
+
"github.com/containers/libpod/pkg/api/handlers"
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error {
+func (s *APIServer) registerEventsHandlers(r *mux.Router) error {
// swagger:operation GET /events system getEvents
// ---
// tags:
@@ -32,6 +34,6 @@ func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error {
// description: returns a string of json data describing an event
// 500:
// "$ref": "#/responses/InternalError"
- r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents))
+ r.Handle(VersionedPath("/events"), s.APIHandler(handlers.GetEvents)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_exec.go b/pkg/api/server/register_exec.go
index dbf04dc19..ad62de3f5 100644
--- a/pkg/api/server/register_exec.go
+++ b/pkg/api/server/register_exec.go
@@ -74,7 +74,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/containers/{name}/create"), APIHandler(s.Context, handlers.CreateExec)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/containers/{name}/create"), s.APIHandler(handlers.CreateExec)).Methods(http.MethodPost)
// swagger:operation POST /exec/{id}/start compat startExec
// ---
// tags:
@@ -110,7 +110,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is stopped or paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/exec/{id}/start"), APIHandler(s.Context, handlers.StartExec)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/exec/{id}/start"), s.APIHandler(handlers.StartExec)).Methods(http.MethodPost)
// swagger:operation POST /exec/{id}/resize compat resizeExec
// ---
// tags:
@@ -141,8 +141,8 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/exec/{id}/resize"), APIHandler(s.Context, handlers.ResizeExec)).Methods(http.MethodPost)
- // swagger:operation GET /exec/{id}/inspect compat inspectExec
+ r.Handle(VersionedPath("/exec/{id}/resize"), s.APIHandler(handlers.ResizeExec)).Methods(http.MethodPost)
+ // swagger:operation GET /exec/{id}/json compat inspectExec
// ---
// tags:
// - exec (compat)
@@ -163,7 +163,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/exec/{id}/json"), APIHandler(s.Context, handlers.InspectExec)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/exec/{id}/json"), s.APIHandler(handlers.InspectExec)).Methods(http.MethodGet)
/*
libpod api follows
@@ -235,7 +235,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/containers/{name}/create"), APIHandler(s.Context, handlers.CreateExec)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/containers/{name}/create"), s.APIHandler(handlers.CreateExec)).Methods(http.MethodPost)
// swagger:operation POST /libpod/exec/{id}/start libpod libpodStartExec
// ---
// tags:
@@ -271,7 +271,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// description: container is stopped or paused
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/exec/{id}/start"), APIHandler(s.Context, handlers.StartExec)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/exec/{id}/start"), s.APIHandler(handlers.StartExec)).Methods(http.MethodPost)
// swagger:operation POST /libpod/exec/{id}/resize libpod libpodResizeExec
// ---
// tags:
@@ -302,8 +302,8 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/exec/{id}/resize"), APIHandler(s.Context, handlers.ResizeExec)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/exec/{id}/inspect libpod libpodInspectExec
+ r.Handle(VersionedPath("/libpod/exec/{id}/resize"), s.APIHandler(handlers.ResizeExec)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/exec/{id}/json libpod libpodInspectExec
// ---
// tags:
// - exec
@@ -324,6 +324,6 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchExecInstance"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/exec/{id}/json"), APIHandler(s.Context, handlers.InspectExec)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/exec/{id}/json"), s.APIHandler(handlers.InspectExec)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_healthcheck.go b/pkg/api/server/register_healthcheck.go
index 1286324f0..5466e2905 100644
--- a/pkg/api/server/register_healthcheck.go
+++ b/pkg/api/server/register_healthcheck.go
@@ -8,6 +8,6 @@ import (
)
func (s *APIServer) registerHealthCheckHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/libpod/containers/{name}/runhealthcheck"), APIHandler(s.Context, libpod.RunHealthCheck)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/containers/{name}/runhealthcheck"), s.APIHandler(libpod.RunHealthCheck)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 4706a7c69..db04ecdc9 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -47,8 +47,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchImage"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromImage)).Methods(http.MethodPost).Queries("fromImage", "{fromImage}")
- r.Handle(VersionedPath("/images/create"), APIHandler(s.Context, generic.CreateImageFromSrc)).Methods(http.MethodPost).Queries("fromSrc", "{fromSrc}")
+ r.Handle(VersionedPath("/images/create"), s.APIHandler(generic.CreateImageFromImage)).Methods(http.MethodPost).Queries("fromImage", "{fromImage}")
+ r.Handle(VersionedPath("/images/create"), s.APIHandler(generic.CreateImageFromSrc)).Methods(http.MethodPost).Queries("fromSrc", "{fromSrc}")
// swagger:operation GET /images/json compat listImages
// ---
// tags:
@@ -83,7 +83,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/DockerImageSummary"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/json"), APIHandler(s.Context, generic.GetImages)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/images/json"), s.APIHandler(generic.GetImages)).Methods(http.MethodGet)
// swagger:operation POST /images/load compat importImage
// ---
// tags:
@@ -107,7 +107,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: no error
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, generic.LoadImages)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/images/load"), s.APIHandler(generic.LoadImages)).Methods(http.MethodPost)
// swagger:operation POST /images/prune compat pruneImages
// ---
// tags:
@@ -132,7 +132,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/DocsImageDeleteResponse"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/prune"), APIHandler(s.Context, generic.PruneImages)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/images/prune"), s.APIHandler(generic.PruneImages)).Methods(http.MethodPost)
// swagger:operation GET /images/search compat searchImages
// ---
// tags:
@@ -161,10 +161,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// responses:
// 200:
// $ref: "#/responses/DocsSearchResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet)
- // swagger:operation DELETE /images/{name} compat removeImage
+ r.Handle(VersionedPath("/images/search"), s.APIHandler(handlers.SearchImages)).Methods(http.MethodGet)
+ // swagger:operation DELETE /images/{name:.*} compat removeImage
// ---
// tags:
// - images (compat)
@@ -172,7 +174,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Delete an image from local storage
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: name or ID of image to delete
@@ -195,8 +197,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/ConflictError'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/{name}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete)
- // swagger:operation GET /images/{name}/get compat exportImage
+ r.Handle(VersionedPath("/images/{name:.*}"), s.APIHandler(handlers.RemoveImage)).Methods(http.MethodDelete)
+ // swagger:operation GET /images/{name:.*}/get compat exportImage
// ---
// tags:
// - images (compat)
@@ -204,7 +206,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Export an image in tarball format
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -218,8 +220,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// format: binary
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/{name}/get"), APIHandler(s.Context, generic.ExportImage)).Methods(http.MethodGet)
- // swagger:operation GET /images/{name}/history compat imageHistory
+ r.Handle(VersionedPath("/images/{name:.*}/get"), s.APIHandler(generic.ExportImage)).Methods(http.MethodGet)
+ // swagger:operation GET /images/{name:.*}/history compat imageHistory
// ---
// tags:
// - images (compat)
@@ -227,7 +229,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Return parent layers of an image.
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -240,8 +242,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchImage"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/images/{name}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet)
- // swagger:operation GET /images/{name}/json compat inspectImage
+ r.Handle(VersionedPath("/images/{name:.*}/history"), s.APIHandler(handlers.HistoryImage)).Methods(http.MethodGet)
+ // swagger:operation GET /images/{name:.*}/json compat inspectImage
// ---
// tags:
// - images (compat)
@@ -249,7 +251,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Return low-level information about an image.
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -262,8 +264,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchImage"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/images/{name}/json"), APIHandler(s.Context, generic.GetImage))
- // swagger:operation POST /images/{name}/tag compat tagImage
+ r.Handle(VersionedPath("/images/{name:.*}/json"), s.APIHandler(generic.GetImage)).Methods(http.MethodGet)
+ // swagger:operation POST /images/{name:.*}/tag compat tagImage
// ---
// tags:
// - images (compat)
@@ -271,7 +273,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Tag an image so that it becomes part of a repository.
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -296,8 +298,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/ConflictError'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/images/{name}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost)
- // swagger:operation POST /commit/ compat commitContainer
+ r.Handle(VersionedPath("/images/{name:.*}/tag"), s.APIHandler(handlers.TagImage)).Methods(http.MethodPost)
+ // swagger:operation POST /commit compat commitContainer
// ---
// tags:
// - containers (compat)
@@ -341,9 +343,9 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/commit"), APIHandler(s.Context, generic.CommitContainer)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/commit"), s.APIHandler(generic.CommitContainer)).Methods(http.MethodPost)
- // swagger:operation POST /build images buildImage
+ // swagger:operation POST /build compat buildImage
// ---
// tags:
// - images
@@ -551,12 +553,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/build"), s.APIHandler(handlers.BuildImage)).Methods(http.MethodPost)
/*
libpod endpoints
*/
- // swagger:operation POST /libpod/images/{name}/exists libpod libpodImageExists
+ // swagger:operation GET /libpod/images/{name:.*}/exists libpod libpodImageExists
// ---
// tags:
// - images
@@ -564,7 +566,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Check if image exists in local store
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -577,8 +579,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/exists"), APIHandler(s.Context, libpod.ImageExists))
- // swagger:operation POST /libpod/images/{name}/tree libpod libpodImageTree
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/exists"), s.APIHandler(libpod.ImageExists)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/images/{name:.*}/tree libpod libpodImageTree
// ---
// tags:
// - images
@@ -586,7 +588,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Retrieve the image tree for the provided image name or ID
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -603,8 +605,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/tree"), APIHandler(s.Context, libpod.ImageTree))
- // swagger:operation GET /libpod/images/{name}/history libpod libpodImageHistory
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/tree"), s.APIHandler(libpod.ImageTree)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/images/{name:.*}/history libpod libpodImageHistory
// ---
// tags:
// - images
@@ -612,7 +614,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Return parent layers of an image.
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -625,7 +627,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/history"), APIHandler(s.Context, handlers.HistoryImage)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/history"), s.APIHandler(handlers.HistoryImage)).Methods(http.MethodGet)
// swagger:operation GET /libpod/images/json libpod libpodListImages
// ---
// tags:
@@ -646,6 +648,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - `dangling=true`
// - `label=key` or `label="key=value"` of an image label
// - `reference`=(`<image-name>[:<tag>]`)
+ // - `id`=(`<image-id>`)
// - `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
// type: string
// produces:
@@ -655,7 +658,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/DockerImageSummary"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/json"), APIHandler(s.Context, libpod.GetImages)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/images/json"), s.APIHandler(libpod.GetImages)).Methods(http.MethodGet)
// swagger:operation POST /libpod/images/load libpod libpodImagesLoad
// ---
// tags:
@@ -681,7 +684,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImagesLoad)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/load"), s.APIHandler(libpod.ImagesLoad)).Methods(http.MethodPost)
// swagger:operation POST /libpod/images/import libpod libpodImagesImport
// ---
// tags:
@@ -721,7 +724,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/import"), s.APIHandler(libpod.ImagesImport)).Methods(http.MethodPost)
// swagger:operation POST /libpod/images/pull libpod libpodImagesPull
// ---
// tags:
@@ -763,7 +766,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/pull"), s.APIHandler(libpod.ImagesPull)).Methods(http.MethodPost)
// swagger:operation POST /libpod/images/prune libpod libpodPruneImages
// ---
// tags:
@@ -788,7 +791,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/DocsImageDeleteResponse"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/prune"), APIHandler(s.Context, libpod.PruneImages)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/prune"), s.APIHandler(libpod.PruneImages)).Methods(http.MethodPost)
// swagger:operation GET /libpod/images/search libpod libpodSearchImages
// ---
// tags:
@@ -819,8 +822,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/DocsSearchResponse"
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/search"), APIHandler(s.Context, handlers.SearchImages)).Methods(http.MethodGet)
- // swagger:operation DELETE /libpod/images/{name} libpod libpodRemoveImage
+ r.Handle(VersionedPath("/libpod/images/search"), s.APIHandler(handlers.SearchImages)).Methods(http.MethodGet)
+ // swagger:operation DELETE /libpod/images/{name:.*} libpod libpodRemoveImage
// ---
// tags:
// - images
@@ -828,7 +831,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Delete an image from local store
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: name or ID of image to delete
@@ -849,8 +852,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/ConflictError'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}"), APIHandler(s.Context, handlers.RemoveImage)).Methods(http.MethodDelete)
- // swagger:operation GET /libpod/images/{name}/get libpod libpoodExportImage
+ r.Handle(VersionedPath("/libpod/images/{name:.*}"), s.APIHandler(handlers.RemoveImage)).Methods(http.MethodDelete)
+ // swagger:operation GET /libpod/images/{name:.*}/get libpod libpodExportImage
// ---
// tags:
// - images
@@ -858,7 +861,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Export an image as a tarball
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -882,8 +885,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/get"), APIHandler(s.Context, libpod.ExportImage)).Methods(http.MethodGet)
- // swagger:operation GET /libpod/images/{name}/json libpod libpodInspectImage
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/get"), s.APIHandler(libpod.ExportImage)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/images/{name:.*}/json libpod libpodInspectImage
// ---
// tags:
// - images
@@ -891,7 +894,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Obtain low-level information about an image
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -904,8 +907,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchImage'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/json"), APIHandler(s.Context, libpod.GetImage))
- // swagger:operation POST /libpod/images/{name}/tag libpod libpodTagImage
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/json"), s.APIHandler(libpod.GetImage)).Methods(http.MethodGet)
+ // swagger:operation POST /libpod/images/{name:.*}/tag libpod libpodTagImage
// ---
// tags:
// - images
@@ -913,7 +916,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Tag an image so that it becomes part of a repository.
// parameters:
// - in: path
- // name: name
+ // name: name:.*
// type: string
// required: true
// description: the name or ID of the container
@@ -938,7 +941,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: '#/responses/ConflictError'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/images/{name}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/tag"), s.APIHandler(handlers.TagImage)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/register_info.go b/pkg/api/server/register_info.go
index 8c50fed7f..36c467cc3 100644
--- a/pkg/api/server/register_info.go
+++ b/pkg/api/server/register_info.go
@@ -21,6 +21,6 @@ func (s *APIServer) registerInfoHandlers(r *mux.Router) error {
// description: to be determined
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/info"), APIHandler(s.Context, generic.GetInfo)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/info"), s.APIHandler(generic.GetInfo)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_monitor.go b/pkg/api/server/register_monitor.go
index e6c235419..dbe0d27ce 100644
--- a/pkg/api/server/register_monitor.go
+++ b/pkg/api/server/register_monitor.go
@@ -5,7 +5,7 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterMonitorHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/monitor"), APIHandler(s.Context, handlers.UnsupportedHandler))
+func (s *APIServer) registerMonitorHandlers(r *mux.Router) error {
+ r.Handle(VersionedPath("/monitor"), s.APIHandler(handlers.UnsupportedHandler))
return nil
}
diff --git a/pkg/api/server/register_ping.go b/pkg/api/server/register_ping.go
index 086e674a1..349a8a71a 100644
--- a/pkg/api/server/register_ping.go
+++ b/pkg/api/server/register_ping.go
@@ -9,8 +9,8 @@ import (
func (s *APIServer) registerPingHandlers(r *mux.Router) error {
- r.Handle("/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodGet)
- r.Handle("/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodHead)
+ r.Handle("/_ping", s.APIHandler(handlers.Ping)).Methods(http.MethodGet)
+ r.Handle("/_ping", s.APIHandler(handlers.Ping)).Methods(http.MethodHead)
// swagger:operation GET /libpod/_ping libpod libpodPingGet
// ---
@@ -61,7 +61,7 @@ func (s *APIServer) registerPingHandlers(r *mux.Router) error {
// determine if talking to Podman engine or another engine
// 500:
// $ref: "#/responses/InternalError"
- r.Handle("/libpod/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodGet)
- r.Handle("/libpod/_ping", APIHandler(s.Context, handlers.Ping)).Methods(http.MethodHead)
+ r.Handle("/libpod/_ping", s.APIHandler(handlers.Ping)).Methods(http.MethodGet)
+ r.Handle("/libpod/_ping", s.APIHandler(handlers.Ping)).Methods(http.MethodHead)
return nil
}
diff --git a/pkg/api/server/register_plugins.go b/pkg/api/server/register_plugins.go
index 7fd6b9c4c..479a79d1f 100644
--- a/pkg/api/server/register_plugins.go
+++ b/pkg/api/server/register_plugins.go
@@ -5,7 +5,7 @@ import (
"github.com/gorilla/mux"
)
-func (s *APIServer) RegisterPluginsHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/plugins"), APIHandler(s.Context, handlers.UnsupportedHandler))
+func (s *APIServer) registerPluginsHandlers(r *mux.Router) error {
+ r.Handle(VersionedPath("/plugins"), s.APIHandler(handlers.UnsupportedHandler))
return nil
}
diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go
index 974568d47..af2330665 100644
--- a/pkg/api/server/register_pods.go
+++ b/pkg/api/server/register_pods.go
@@ -25,8 +25,27 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/json"), APIHandler(s.Context, libpod.Pods)).Methods(http.MethodGet)
- r.Handle(VersionedPath("/libpod/pods/create"), APIHandler(s.Context, libpod.PodCreate)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/json"), s.APIHandler(libpod.Pods)).Methods(http.MethodGet)
+ // swagger:operation POST /libpod/pods/create pods CreatePod
+ // ---
+ // summary: Create a pod
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: body
+ // name: create
+ // description: attributes for creating a pod
+ // schema:
+ // type: object
+ // $ref: "#/definitions/PodCreateConfig"
+ // responses:
+ // 200:
+ // $ref: "#/definitions/IdResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/pods/create"), s.APIHandler(libpod.PodCreate)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/prune pods PrunePods
// ---
// summary: Prune unused pods
@@ -45,7 +64,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// description: pod already exists
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/prune"), APIHandler(s.Context, libpod.PodPrune)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/prune"), s.APIHandler(libpod.PodPrune)).Methods(http.MethodPost)
// swagger:operation DELETE /libpod/pods/{name} pods removePod
// ---
// summary: Remove pod
@@ -70,7 +89,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}"), APIHandler(s.Context, libpod.PodDelete)).Methods(http.MethodDelete)
+ r.Handle(VersionedPath("/libpod/pods/{name}"), s.APIHandler(libpod.PodDelete)).Methods(http.MethodDelete)
// swagger:operation GET /libpod/pods/{name}/json pods inspectPod
// ---
// summary: Inspect pod
@@ -89,7 +108,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/json"), APIHandler(s.Context, libpod.PodInspect)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/pods/{name}/json"), s.APIHandler(libpod.PodInspect)).Methods(http.MethodGet)
// swagger:operation GET /libpod/pods/{name}/exists pods podExists
// ---
// summary: Pod exists
@@ -109,7 +128,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/exists"), APIHandler(s.Context, libpod.PodExists)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/pods/{name}/exists"), s.APIHandler(libpod.PodExists)).Methods(http.MethodGet)
// swagger:operation POST /libpod/pods/{name}/kill pods killPod
// ---
// summary: Kill a pod
@@ -137,7 +156,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/kill"), APIHandler(s.Context, libpod.PodKill)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/kill"), s.APIHandler(libpod.PodKill)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/{name}/pause pods pausePod
// ---
// summary: Pause a pod
@@ -157,7 +176,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/pause"), APIHandler(s.Context, libpod.PodPause)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/pause"), s.APIHandler(libpod.PodPause)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/{name}/restart pods restartPod
// ---
// summary: Restart a pod
@@ -176,7 +195,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/restart"), APIHandler(s.Context, libpod.PodRestart)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/restart"), s.APIHandler(libpod.PodRestart)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/{name}/start pods startPod
// ---
// summary: Start a pod
@@ -197,7 +216,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/start"), APIHandler(s.Context, libpod.PodStart)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/start"), s.APIHandler(libpod.PodStart)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/{name}/stop pods stopPod
// ---
// summary: Stop a pod
@@ -224,7 +243,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/stop"), APIHandler(s.Context, libpod.PodStop)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/stop"), s.APIHandler(libpod.PodStop)).Methods(http.MethodPost)
// swagger:operation POST /libpod/pods/{name}/unpause pods unpausePod
// ---
// summary: Unpause a pod
@@ -243,6 +262,6 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchPod"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/pods/{name}/unpause"), APIHandler(s.Context, libpod.PodUnpause)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/pods/{name}/unpause"), s.APIHandler(libpod.PodUnpause)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/register_swarm.go b/pkg/api/server/register_swarm.go
index 63d8acfde..e37ac4e41 100644
--- a/pkg/api/server/register_swarm.go
+++ b/pkg/api/server/register_swarm.go
@@ -9,7 +9,7 @@ import (
"github.com/sirupsen/logrus"
)
-func (s *APIServer) RegisterSwarmHandlers(r *mux.Router) error {
+func (s *APIServer) registerSwarmHandlers(r *mux.Router) error {
r.PathPrefix("/v{version:[0-9.]+}/configs/").HandlerFunc(noSwarm)
r.PathPrefix("/v{version:[0-9.]+}/nodes/").HandlerFunc(noSwarm)
r.PathPrefix("/v{version:[0-9.]+}/secrets/").HandlerFunc(noSwarm)
diff --git a/pkg/api/server/register_system.go b/pkg/api/server/register_system.go
index f0eaeffd2..188c1cdac 100644
--- a/pkg/api/server/register_system.go
+++ b/pkg/api/server/register_system.go
@@ -1,11 +1,13 @@
package server
import (
+ "net/http"
+
"github.com/containers/libpod/pkg/api/handlers/generic"
"github.com/gorilla/mux"
)
func (s *APIServer) registerSystemHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/system/df"), APIHandler(s.Context, generic.GetDiskUsage))
+ r.Handle(VersionedPath("/system/df"), s.APIHandler(generic.GetDiskUsage)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_version.go b/pkg/api/server/register_version.go
index d3b47c2a9..ee01ad4b3 100644
--- a/pkg/api/server/register_version.go
+++ b/pkg/api/server/register_version.go
@@ -1,12 +1,14 @@
package server
import (
+ "net/http"
+
"github.com/containers/libpod/pkg/api/handlers"
"github.com/gorilla/mux"
)
func (s *APIServer) registerVersionHandlers(r *mux.Router) error {
- r.Handle("/version", APIHandler(s.Context, handlers.VersionHandler))
- r.Handle(VersionedPath("/version"), APIHandler(s.Context, handlers.VersionHandler))
+ r.Handle("/version", s.APIHandler(handlers.VersionHandler)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/version"), s.APIHandler(handlers.VersionHandler)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_volumes.go b/pkg/api/server/register_volumes.go
index d34c71238..d1317904b 100644
--- a/pkg/api/server/register_volumes.go
+++ b/pkg/api/server/register_volumes.go
@@ -11,16 +11,43 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// swagger:operation POST /libpod/volumes/create volumes createVolume
// ---
// summary: Create a volume
+ // parameters:
+ // - in: body
+ // name: create
+ // description: attributes for creating a container
+ // schema:
+ // $ref: "#/definitions/VolumeCreate"
+ // produces:
+ // - application/json
+ // responses:
+ // '201':
+ // $ref: "#/responses/VolumeCreateResponse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/volumes/create"), s.APIHandler(libpod.CreateVolume)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/volumes/json volumes listVolumes
+ // ---
+ // summary: List volumes
+ // description: Returns a list of networks
// produces:
// - application/json
+ // parameters:
+ // - in: query
+ // name: filters
+ // type: string
+ // description: |
+ // JSON encoded value of the filters (a map[string][]string) to process on the networks list. Available filters:
+ // - driver=<volume-driver-name> Matches volumes based on their driver.
+ // - label=<key> or label=<key>:<value> Matches volumes based on the presence of a label alone or a label and a value.
+ // - name=<volume-name> Matches all of volume name.
+ // - opt=<driver-option> Matches a storage driver options
// responses:
// '200':
- // description: tbd
+ // "$ref": "#/responses/VolumeList"
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/create", APIHandler(s.Context, libpod.CreateVolume)).Methods(http.MethodPost)
- r.Handle("/libpod/volumes/json", APIHandler(s.Context, libpod.ListVolumes)).Methods(http.MethodGet)
- // swagger:operation POST /volumes/prune volumes pruneVolumes
+ r.Handle(VersionedPath("/libpod/volumes/json"), s.APIHandler(libpod.ListVolumes)).Methods(http.MethodGet)
+ // swagger:operation POST /libpod/volumes/prune volumes pruneVolumes
// ---
// summary: Prune volumes
// produces:
@@ -30,8 +57,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// description: no error
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/prune", APIHandler(s.Context, libpod.PruneVolumes)).Methods(http.MethodPost)
- // swagger:operation GET /volumes/{name}/json volumes inspectVolume
+ r.Handle(VersionedPath("/libpod/volumes/prune"), s.APIHandler(libpod.PruneVolumes)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/volumes/{name}/json volumes inspectVolume
// ---
// summary: Inspect volume
// parameters:
@@ -49,8 +76,8 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// "$ref": "#/responses/NoSuchVolume"
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/{name}/json", APIHandler(s.Context, libpod.InspectVolume)).Methods(http.MethodGet)
- // swagger:operation DELETE /volumes/{name} volumes removeVolume
+ r.Handle(VersionedPath("/libpod/volumes/{name}/json"), s.APIHandler(libpod.InspectVolume)).Methods(http.MethodGet)
+ // swagger:operation DELETE /libpod/volumes/{name} volumes removeVolume
// ---
// summary: Remove volume
// parameters:
@@ -68,12 +95,12 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// responses:
// 204:
// description: no error
- // 400:
- // $ref: "#/responses/BadParamError"
// 404:
// $ref: "#/responses/NoSuchVolume"
+ // 409:
+ // description: Volume is in use and cannot be removed
// 500:
// $ref: "#/responses/InternalError"
- r.Handle("/libpod/volumes/{name}", APIHandler(s.Context, libpod.RemoveVolume)).Methods(http.MethodDelete)
+ r.Handle(VersionedPath("/libpod/volumes/{name}"), s.APIHandler(libpod.RemoveVolume)).Methods(http.MethodDelete)
return nil
}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 2c709bc59..a5922e5d7 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -20,20 +20,26 @@ import (
)
type APIServer struct {
- http.Server // The HTTP work happens here
- *schema.Decoder // Decoder for Query parameters to structs
- context.Context // Context to carry objects to handlers
- *libpod.Runtime // Where the real work happens
- net.Listener // mux for routing HTTP API calls to libpod routines
- context.CancelFunc // Stop APIServer
- *time.Timer // Hold timer for sliding window
- time.Duration // Duration of client access sliding window
+ http.Server // The HTTP work happens here
+ *schema.Decoder // Decoder for Query parameters to structs
+ context.Context // Context to carry objects to handlers
+ *libpod.Runtime // Where the real work happens
+ net.Listener // mux for routing HTTP API calls to libpod routines
+ context.CancelFunc // Stop APIServer
+ *time.Timer // Hold timer for sliding window
+ time.Duration // Duration of client access sliding window
+ ActiveConnections uint64 // Number of handlers holding a connection
+ TotalConnections uint64 // Number of connections handled
+ ConnectionCh chan int // Channel for signalling handler enter/exit
}
// Number of seconds to wait for next request, if exceeded shutdown server
const (
DefaultServiceDuration = 300 * time.Second
UnlimitedServiceDuration = 0 * time.Second
+ EnterHandler = 1
+ ExitHandler = -1
+ NOOPHandler = 0
)
// NewServer will create and configure a new API server with all defaults
@@ -68,31 +74,19 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
Server: http.Server{
Handler: router,
ReadHeaderTimeout: 20 * time.Second,
- ReadTimeout: 20 * time.Second,
- WriteTimeout: 2 * time.Minute,
+ IdleTimeout: duration,
},
- Decoder: handlers.NewAPIDecoder(),
- Context: nil,
- Runtime: runtime,
- Listener: *listener,
- CancelFunc: nil,
- Duration: duration,
+ Decoder: handlers.NewAPIDecoder(),
+ Runtime: runtime,
+ Listener: *listener,
+ Duration: duration,
+ ConnectionCh: make(chan int),
}
+
server.Timer = time.AfterFunc(server.Duration, func() {
- if err := server.Shutdown(); err != nil {
- logrus.Errorf("unable to shutdown server: %q", err)
- }
+ server.ConnectionCh <- NOOPHandler
})
- ctx, cancelFn := context.WithCancel(context.Background())
- server.CancelFunc = cancelFn
-
- // TODO: Use ConnContext when ported to go 1.13
- ctx = context.WithValue(ctx, "decoder", server.Decoder)
- ctx = context.WithValue(ctx, "runtime", runtime)
- ctx = context.WithValue(ctx, "shutdownFunc", server.Shutdown)
- server.Context = ctx
-
router.NotFoundHandler = http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// We can track user errors...
@@ -102,20 +96,19 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
)
for _, fn := range []func(*mux.Router) error{
- server.RegisterAuthHandlers,
- server.RegisterContainersHandlers,
- server.RegisterDistributionHandlers,
+ server.registerAuthHandlers,
+ server.registerContainersHandlers,
+ server.registerDistributionHandlers,
server.registerExecHandlers,
- server.RegisterEventsHandlers,
+ server.registerEventsHandlers,
server.registerHealthCheckHandlers,
server.registerImagesHandlers,
server.registerInfoHandlers,
- server.RegisterMonitorHandlers,
+ server.registerMonitorHandlers,
server.registerPingHandlers,
- server.RegisterPluginsHandlers,
+ server.registerPluginsHandlers,
server.registerPodsHandlers,
- server.RegisterSwaggerHandlers,
- server.RegisterSwarmHandlers,
+ server.registerSwarmHandlers,
server.registerSystemHandlers,
server.registerVersionHandlers,
server.registerVolumeHandlers,
@@ -145,7 +138,36 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
// Serve starts responding to HTTP requests
func (s *APIServer) Serve() error {
- defer s.CancelFunc()
+ // stalker to count the connections. Should the timer expire it will shutdown the service.
+ go func() {
+ for delta := range s.ConnectionCh {
+ switch delta {
+ case EnterHandler:
+ s.Timer.Stop()
+ s.ActiveConnections += 1
+ s.TotalConnections += 1
+ case ExitHandler:
+ s.Timer.Stop()
+ s.ActiveConnections -= 1
+ if s.ActiveConnections == 0 {
+ // Server will be shutdown iff the timer expires before being reset or stopped
+ s.Timer = time.AfterFunc(s.Duration, func() {
+ if err := s.Shutdown(); err != nil {
+ logrus.Errorf("Failed to shutdown APIServer: %v", err)
+ os.Exit(1)
+ }
+ })
+ } else {
+ s.Timer.Reset(s.Duration)
+ }
+ case NOOPHandler:
+ // push the check out another duration...
+ s.Timer.Reset(s.Duration)
+ default:
+ logrus.Errorf("ConnectionCh received unsupported input %d", delta)
+ }
+ }
+ }()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
@@ -155,6 +177,7 @@ func (s *APIServer) Serve() error {
err := s.Server.Serve(s.Listener)
if err != nil && err != http.ErrServerClosed {
errChan <- errors.Wrap(err, "Failed to start APIServer")
+ return
}
errChan <- nil
}()
@@ -171,27 +194,23 @@ func (s *APIServer) Serve() error {
// Shutdown is a clean shutdown waiting on existing clients
func (s *APIServer) Shutdown() error {
- // Duration == 0 flags no auto-shutdown of server
+ // Duration == 0 flags no auto-shutdown of the server
if s.Duration == 0 {
+ logrus.Debug("APIServer.Shutdown ignored as Duration == 0")
return nil
}
+ logrus.Debugf("APIServer.Shutdown called %v, conn %d/%d", time.Now(), s.ActiveConnections, s.TotalConnections)
- // We're still in the sliding service window
- if s.Timer.Stop() {
- s.Timer.Reset(s.Duration)
- return nil
- }
+ // Gracefully shutdown server
+ ctx, cancel := context.WithTimeout(context.Background(), s.Duration)
+ defer cancel()
- // We've been idle for the service window, really shutdown
go func() {
- err := s.Server.Shutdown(s.Context)
- if err != nil && err != context.Canceled {
+ err := s.Server.Shutdown(ctx)
+ if err != nil && err != context.Canceled && err != http.ErrServerClosed {
logrus.Errorf("Failed to cleanly shutdown APIServer: %s", err.Error())
}
}()
-
- // Wait for graceful shutdown vs. just killing connections and dropping data
- <-s.Context.Done()
return nil
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index fc409d816..011196e5a 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -1,6 +1,7 @@
package server
import (
+ "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
)
@@ -139,3 +140,19 @@ type ok struct {
ok string
}
}
+
+// Volume create response
+// swagger:response VolumeCreateResponse
+type swagVolumeCreateResponse struct {
+ // in:body
+ Body struct {
+ libpod.VolumeConfig
+ }
+}
+
+// Volume list
+// swagger:response VolumeList
+type swagVolumeListResponse struct {
+ // in:body
+ Body []libpod.Volume
+}
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index f270060a6..ba5f9c3aa 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -1,22 +1,34 @@
package bindings
import (
+ "bufio"
"context"
"fmt"
"io"
+ "io/ioutil"
"net"
"net/http"
"net/url"
+ "os"
"path/filepath"
+ "strconv"
"strings"
+ "time"
"github.com/containers/libpod/pkg/api/handlers"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/crypto/ssh"
+ "k8s.io/client-go/util/homedir"
)
var (
- defaultConnectionPath string = filepath.Join(fmt.Sprintf("v%s", handlers.MinimalApiVersion), "libpod")
+ basePath = &url.URL{
+ Scheme: "http",
+ Host: "d",
+ Path: "/v" + handlers.MinimalApiVersion + "/libpod",
+ }
)
type APIResponse struct {
@@ -25,9 +37,28 @@ type APIResponse struct {
}
type Connection struct {
- scheme string
- address string
- client *http.Client
+ _url *url.URL
+ client *http.Client
+}
+
+type valueKey string
+
+const (
+ clientKey = valueKey("client")
+)
+
+// GetClient from context build by NewConnection()
+func GetClient(ctx context.Context) (*Connection, error) {
+ c, ok := ctx.Value(clientKey).(*Connection)
+ if !ok {
+ return nil, errors.Errorf("ClientKey not set in context")
+ }
+ return c, nil
+}
+
+// JoinURL elements with '/'
+func JoinURL(elements ...string) string {
+ return strings.Join(elements, "/")
}
// NewConnection takes a URI as a string and returns a context with the
@@ -36,46 +67,81 @@ type Connection struct {
//
// A valid URI connection should be scheme://
// For example tcp://localhost:<port>
-// or unix://run/podman/podman.sock
-func NewConnection(uri string) (context.Context, error) {
- u, err := url.Parse(uri)
- if err != nil {
- return nil, err
- }
- // TODO once ssh is implemented, remove this block and
- // add it to the conditional beneath it
- if u.Scheme == "ssh" {
- return nil, ErrNotImplemented
+// or unix:///run/podman/podman.sock
+// or ssh://<user>@<host>[:port]/run/podman/podman.sock?secure=True
+func NewConnection(ctx context.Context, uri string, identity ...string) (context.Context, error) {
+ var (
+ err error
+ secure bool
+ )
+ if v, found := os.LookupEnv("PODMAN_HOST"); found {
+ uri = v
}
- if u.Scheme != "tcp" && u.Scheme != "unix" {
- return nil, errors.Errorf("%s is not a support schema", u.Scheme)
+
+ if v, found := os.LookupEnv("PODMAN_SSHKEY"); found {
+ identity = []string{v}
}
- if u.Scheme == "tcp" && !strings.HasPrefix(uri, "tcp://") {
- return nil, errors.New("tcp URIs should begin with tcp://")
+ _url, err := url.Parse(uri)
+ if err != nil {
+ return nil, errors.Wrapf(err, "Value of PODMAN_HOST is not a valid url: %s", uri)
}
- address := u.Path
- if u.Scheme == "tcp" {
- address = u.Host
+ // Now we setup the http client to use the connection above
+ var client *http.Client
+ switch _url.Scheme {
+ case "ssh":
+ secure, err = strconv.ParseBool(_url.Query().Get("secure"))
+ if err != nil {
+ secure = false
+ }
+ client, err = sshClient(_url, identity[0], secure)
+ case "unix":
+ if !strings.HasPrefix(uri, "unix:///") {
+ // autofix unix://path_element vs unix:///path_element
+ _url.Path = JoinURL(_url.Host, _url.Path)
+ _url.Host = ""
+ }
+ client, err = unixClient(_url)
+ case "tcp":
+ if !strings.HasPrefix(uri, "tcp://") {
+ return nil, errors.New("tcp URIs should begin with tcp://")
+ }
+ client, err = tcpClient(_url)
+ default:
+ return nil, errors.Errorf("%s is not a support schema", _url.Scheme)
+ }
+ if err != nil {
+ return nil, errors.Wrapf(err, "Failed to create %sClient", _url.Scheme)
}
- newConn := newConnection(u.Scheme, address)
- ctx := context.WithValue(context.Background(), "conn", &newConn)
+
+ ctx = context.WithValue(ctx, clientKey, &Connection{_url, client})
if err := pingNewConnection(ctx); err != nil {
return nil, err
}
return ctx, nil
}
+func tcpClient(_url *url.URL) (*http.Client, error) {
+ return &http.Client{
+ Transport: &http.Transport{
+ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
+ return net.Dial("tcp", _url.Path)
+ },
+ DisableCompression: true,
+ },
+ }, nil
+}
+
// pingNewConnection pings to make sure the RESTFUL service is up
// and running. it should only be used where initializing a connection
func pingNewConnection(ctx context.Context) error {
- conn, err := GetConnectionFromContext(ctx)
+ client, err := GetClient(ctx)
if err != nil {
return err
}
// the ping endpoint sits at / in this case
- response, err := conn.DoRequest(nil, http.MethodGet, "../../../_ping", nil)
+ response, err := client.DoRequest(nil, http.MethodGet, "../../../_ping", nil)
if err != nil {
return err
}
@@ -85,30 +151,62 @@ func pingNewConnection(ctx context.Context) error {
return errors.Errorf("ping response was %q", response.StatusCode)
}
-// newConnection takes a scheme and address and creates a connection from it
-func newConnection(scheme, address string) Connection {
- client := http.Client{
- Transport: &http.Transport{
- DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
- return net.Dial(scheme, address)
+func sshClient(_url *url.URL, identity string, secure bool) (*http.Client, error) {
+ auth, err := publicKey(identity)
+ if err != nil {
+ return nil, errors.Wrapf(err, "Failed to parse identity %s: %v\n", _url.String(), identity)
+ }
+
+ callback := ssh.InsecureIgnoreHostKey()
+ if secure {
+ key := hostKey(_url.Hostname())
+ if key != nil {
+ callback = ssh.FixedHostKey(key)
+ }
+ }
+
+ bastion, err := ssh.Dial("tcp",
+ net.JoinHostPort(_url.Hostname(), _url.Port()),
+ &ssh.ClientConfig{
+ User: _url.User.Username(),
+ Auth: []ssh.AuthMethod{auth},
+ HostKeyCallback: callback,
+ HostKeyAlgorithms: []string{
+ ssh.KeyAlgoRSA,
+ ssh.KeyAlgoDSA,
+ ssh.KeyAlgoECDSA256,
+ ssh.KeyAlgoECDSA384,
+ ssh.KeyAlgoECDSA521,
+ ssh.KeyAlgoED25519,
},
+ Timeout: 5 * time.Second,
},
+ )
+ if err != nil {
+ return nil, errors.Wrapf(err, "Connection to bastion host (%s) failed.", _url.String())
}
- newConn := Connection{
- client: &client,
- address: address,
- scheme: scheme,
- }
- return newConn
+ return &http.Client{
+ Transport: &http.Transport{
+ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
+ return bastion.Dial("unix", _url.Path)
+ },
+ }}, nil
}
-func (c *Connection) makeEndpoint(u string) string {
- // The d character in the url is discarded and is meaningless
- return fmt.Sprintf("http://d/%s%s", defaultConnectionPath, u)
+func unixClient(_url *url.URL) (*http.Client, error) {
+ return &http.Client{
+ Transport: &http.Transport{
+ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
+ d := net.Dialer{}
+ return d.DialContext(ctx, "unix", _url.Path)
+ },
+ DisableCompression: true,
+ },
+ }, nil
}
// DoRequest assembles the http request and returns the response
-func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams map[string]string, pathValues ...string) (*APIResponse, error) {
+func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, queryParams url.Values, pathValues ...string) (*APIResponse, error) {
var (
err error
response *http.Response
@@ -121,18 +219,13 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
// Lets eventually use URL for this which might lead to safer
// usage
safeEndpoint := fmt.Sprintf(endpoint, safePathValues...)
- e := c.makeEndpoint(safeEndpoint)
+ e := basePath.String() + safeEndpoint
req, err := http.NewRequest(httpMethod, e, httpBody)
if err != nil {
return nil, err
}
if len(queryParams) > 0 {
- // 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, v)
- }
- req.URL.RawQuery = r.Encode()
+ req.URL.RawQuery = queryParams.Encode()
}
// Give the Do three chances in the case of a comm/service hiccup
for i := 0; i < 3; i++ {
@@ -140,21 +233,11 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
if err == nil {
break
}
+ time.Sleep(time.Duration(i*100) * time.Millisecond)
}
return &APIResponse{response, req}, err
}
-// GetConnectionFromContext returns a bindings connection from the context
-// being passed into each method.
-func GetConnectionFromContext(ctx context.Context) (*Connection, error) {
- c := ctx.Value("conn")
- if c == nil {
- return nil, errors.New("unable to get connection from context")
- }
- conn := c.(*Connection)
- return conn, nil
-}
-
// FiltersToString converts our typical filter format of a
// map[string][]string to a query/html safe string.
func FiltersToString(filters map[string][]string) (string, error) {
@@ -189,3 +272,45 @@ func (h *APIResponse) IsClientError() bool {
func (h *APIResponse) IsServerError() bool {
return h.Response.StatusCode/100 == 5
}
+
+func publicKey(path string) (ssh.AuthMethod, error) {
+ key, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+
+ signer, err := ssh.ParsePrivateKey(key)
+ if err != nil {
+ return nil, err
+ }
+
+ return ssh.PublicKeys(signer), nil
+}
+
+func hostKey(host string) ssh.PublicKey {
+ // parse OpenSSH known_hosts file
+ // ssh or use ssh-keyscan to get initial key
+ known_hosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts")
+ fd, err := os.Open(known_hosts)
+ if err != nil {
+ logrus.Error(err)
+ return nil
+ }
+
+ scanner := bufio.NewScanner(fd)
+ for scanner.Scan() {
+ _, hosts, key, _, _, err := ssh.ParseKnownHosts(scanner.Bytes())
+ if err != nil {
+ logrus.Errorf("Failed to parse known_hosts: %s", scanner.Text())
+ continue
+ }
+
+ for _, h := range hosts {
+ if h == host {
+ return key
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 04f7f8802..2985787a6 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -3,6 +3,7 @@ package containers
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod"
@@ -16,33 +17,33 @@ import (
// 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, all *bool, last *int, pod, size, sync *bool) ([]lpapiv2.ListContainer, error) { // nolint:typecheck
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
var containers []lpapiv2.ListContainer
- params := make(map[string]string)
+ params := url.Values{}
if all != nil {
- params["all"] = strconv.FormatBool(*all)
+ params.Set("all", strconv.FormatBool(*all))
}
if last != nil {
- params["last"] = strconv.Itoa(*last)
+ params.Set("last", strconv.Itoa(*last))
}
if pod != nil {
- params["pod"] = strconv.FormatBool(*pod)
+ params.Set("pod", strconv.FormatBool(*pod))
}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
if sync != nil {
- params["sync"] = strconv.FormatBool(*sync)
+ params.Set("sync", strconv.FormatBool(*sync))
}
if filters != nil {
filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = filterString
+ params.Set("filters", filterString)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params)
if err != nil {
@@ -59,17 +60,17 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
var (
pruneResponse []string
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = filterString
+ params.Set("filters", filterString)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/prune", params)
if err != nil {
@@ -82,16 +83,16 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
// that the container should be removed forcibly (example, even it is running). The volumes
// bool dictates that a container's volumes should also be removed.
func Remove(ctx context.Context, nameOrID string, force, volumes *bool) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
if volumes != nil {
- params["vols"] = strconv.FormatBool(*volumes)
+ params.Set("vols", strconv.FormatBool(*volumes))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/containers/%s", params, nameOrID)
if err != nil {
@@ -105,13 +106,13 @@ func Remove(ctx context.Context, nameOrID string, force, volumes *bool) error {
// should be calculated. Calculating the size of a container requires extra work from the filesystem and
// is therefore slower.
func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectContainerData, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/json", params, nameOrID)
if err != nil {
@@ -125,12 +126,12 @@ func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectC
// representation of a signal like 'SIGKILL'. The nameOrID can be a container name
// or a partial/full ID
func Kill(ctx context.Context, nameOrID string, signal string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
- params["signal"] = signal
+ params := url.Values{}
+ params.Set("signal", signal)
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/kill", params, nameOrID)
if err != nil {
return err
@@ -143,7 +144,7 @@ func Logs() {}
// Pause pauses a given container. The nameOrID can be a container name
// or a partial/full ID.
func Pause(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -158,13 +159,13 @@ func Pause(ctx context.Context, nameOrID string) error {
// or a partial/full ID. The optional timeout specifies the number of seconds to wait
// for the running container to stop before killing it.
func Restart(ctx context.Context, nameOrID string, timeout *int) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restart", params, nameOrID)
if err != nil {
@@ -177,13 +178,13 @@ func Restart(ctx context.Context, nameOrID string, timeout *int) error {
// or a partial/full ID. The optional parameter for detach keys are to override the default
// detach key sequence.
func Start(ctx context.Context, nameOrID string, detachKeys *string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if detachKeys != nil {
- params["detachKeys"] = *detachKeys
+ params.Set("detachKeys", *detachKeys)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/start", params, nameOrID)
if err != nil {
@@ -198,7 +199,7 @@ func Top() {}
// Unpause resumes the given paused container. The nameOrID can be a container name
// or a partial/full ID.
func Unpause(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -213,7 +214,7 @@ func Unpause(ctx context.Context, nameOrID string) error {
// or a partial/full ID.
func Wait(ctx context.Context, nameOrID string) (int32, error) {
var exitCode int32
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return exitCode, err
}
@@ -228,7 +229,7 @@ func Wait(ctx context.Context, nameOrID string) (int32, error) {
// exists in local storage. The nameOrID can be a container name
// or a partial/full ID.
func Exists(ctx context.Context, nameOrID string) (bool, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return false, err
}
@@ -242,13 +243,13 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
// Stop stops a running container. The timeout is optional. The nameOrID can be a container name
// or a partial/full ID
func Stop(ctx context.Context, nameOrID string, timeout *int) error {
- params := make(map[string]string)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ params := url.Values{}
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/stop", params, nameOrID)
if err != nil {
diff --git a/pkg/bindings/containers/create.go b/pkg/bindings/containers/create.go
new file mode 100644
index 000000000..43a3ef02d
--- /dev/null
+++ b/pkg/bindings/containers/create.go
@@ -0,0 +1,30 @@
+package containers
+
+import (
+ "context"
+ "net/http"
+ "strings"
+
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/specgen"
+ jsoniter "github.com/json-iterator/go"
+)
+
+func CreateWithSpec(ctx context.Context, s specgen.SpecGenerator) (utils.ContainerCreateResponse, error) {
+ var ccr utils.ContainerCreateResponse
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return ccr, err
+ }
+ specgenString, err := jsoniter.MarshalToString(s)
+ if err != nil {
+ return ccr, err
+ }
+ stringReader := strings.NewReader(specgenString)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/containers/create", nil)
+ if err != nil {
+ return ccr, err
+ }
+ return ccr, response.Process(&ccr)
+}
diff --git a/pkg/bindings/containers/healthcheck.go b/pkg/bindings/containers/healthcheck.go
index 9ed7f858d..dc607c1b3 100644
--- a/pkg/bindings/containers/healthcheck.go
+++ b/pkg/bindings/containers/healthcheck.go
@@ -11,7 +11,7 @@ import (
// RunHealthCheck executes the container's healthcheck and returns the health status of the
// container.
func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckStatus, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/mount.go b/pkg/bindings/containers/mount.go
index d68dee981..e0627d9a3 100644
--- a/pkg/bindings/containers/mount.go
+++ b/pkg/bindings/containers/mount.go
@@ -10,7 +10,7 @@ import (
// Mount mounts an existing container to the filesystem. It returns the path
// of the mounted container in string format.
func Mount(ctx context.Context, nameOrID string) (string, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return "", err
}
@@ -27,7 +27,7 @@ func Mount(ctx context.Context, nameOrID string) (string, error) {
// Unmount unmounts a container from the filesystem. The container must not be running
// or the unmount will fail.
func Unmount(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -40,7 +40,7 @@ func Unmount(ctx context.Context, nameOrID string) error {
// GetMountedContainerPaths returns a map of mounted containers and their mount locations.
func GetMountedContainerPaths(ctx context.Context) (map[string]string, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
index 1bcaac3f0..5fa711199 100644
--- a/pkg/bindings/errors.go
+++ b/pkg/bindings/errors.go
@@ -25,7 +25,7 @@ func (a APIResponse) Process(unmarshalInto interface{}) error {
if err != nil {
return errors.Wrap(err, "unable to process API response")
}
- if a.IsSuccess() {
+ if a.IsSuccess() || a.IsRedirection() {
if unmarshalInto != nil {
return json.Unmarshal(data, unmarshalInto)
}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index b19482943..c84aa4601 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -2,8 +2,10 @@ package images
import (
"context"
+ "errors"
"io"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/pkg/api/handlers"
@@ -14,7 +16,7 @@ import (
// Exists a lightweight way to determine if an image exists in local storage. It returns a
// boolean response.
func Exists(ctx context.Context, nameOrID string) (bool, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return false, err
}
@@ -29,20 +31,20 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
// ways to alter the image query.
func List(ctx context.Context, all *bool, filters map[string][]string) ([]*handlers.ImageSummary, error) {
var imageSummary []*handlers.ImageSummary
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if all != nil {
- params["all"] = strconv.FormatBool(*all)
+ params.Set("all", strconv.FormatBool(*all))
}
if filters != nil {
strFilters, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = strFilters
+ params.Set("filters", strFilters)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params)
if err != nil {
@@ -54,13 +56,13 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*handl
// Get performs an image inspect. To have the on-disk size of the image calculated, you can
// use the optional size parameter.
func GetImage(ctx context.Context, nameOrID string, size *bool) (*inspect.ImageData, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if size != nil {
- params["size"] = strconv.FormatBool(*size)
+ params.Set("size", strconv.FormatBool(*size))
}
inspectedData := inspect.ImageData{}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
@@ -77,7 +79,7 @@ func ImageTree(ctx context.Context, nameOrId string) error {
// History returns the parent layers of an image.
func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse, error) {
var history []*handlers.HistoryResponse
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
@@ -88,28 +90,34 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
return history, response.Process(&history)
}
-func Load(ctx context.Context, r io.Reader) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
+ var id handlers.IDResponse
+ conn, err := bindings.GetClient(ctx)
if err != nil {
- return err
+ return "", err
}
- // TODO this still needs error handling added
- //_, err := http.Post(c.makeEndpoint("/images/loads"), "application/json", r) //nolint
- _ = conn
- return bindings.ErrNotImplemented
+ params := url.Values{}
+ if name != nil {
+ params.Set("reference", *name)
+ }
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
+ if err != nil {
+ return "", err
+ }
+ return id.ID, response.Process(&id)
}
// Remove deletes an image from local storage. The optional force parameter will forcibly remove
// the image by removing all all containers, including those that are Running, first.
func Remove(ctx context.Context, nameOrID string, force *bool) ([]map[string]string, error) {
var deletes []map[string]string
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/images/%s", params, nameOrID)
if err != nil {
@@ -121,16 +129,16 @@ func Remove(ctx context.Context, nameOrID string, force *bool) ([]map[string]str
// Export saves an image from local storage as a tarball or image archive. The optional format
// parameter is used to change the format of the output.
func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, compress *bool) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if format != nil {
- params["format"] = *format
+ params.Set("format", *format)
}
if compress != nil {
- params["compress"] = strconv.FormatBool(*compress)
+ params.Set("compress", strconv.FormatBool(*compress))
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nameOrID)
if err != nil {
@@ -149,17 +157,17 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
var (
deleted []string
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params)
if err != nil {
@@ -170,13 +178,13 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
// Tag adds an additional name to locally-stored image. Both the tag and repo parameters are required.
func Tag(ctx context.Context, nameOrID, tag, repo string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
- params["tag"] = tag
- params["repo"] = repo
+ params := url.Values{}
+ params.Set("tag", tag)
+ params.Set("repo", repo)
response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nameOrID)
if err != nil {
return err
@@ -185,3 +193,35 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error {
}
func Build(nameOrId string) {}
+
+// Imports adds the given image to the local image store. This can be done by file and the given reader
+// or via the url parameter. Additional metadata can be associated with the image by using the changes and
+// message parameters. The image can also be tagged given a reference. One of url OR r must be provided.
+func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (string, error) {
+ var id handlers.IDResponse
+ if r != nil && u != nil {
+ return "", errors.New("url and r parameters cannot be used together")
+ }
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return "", err
+ }
+ params := url.Values{}
+ for _, change := range changes {
+ params.Add("changes", change)
+ }
+ if message != nil {
+ params.Set("message", *message)
+ }
+ if reference != nil {
+ params.Set("reference", *reference)
+ }
+ if u != nil {
+ params.Set("url", *u)
+ }
+ response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params)
+ if err != nil {
+ return "", err
+ }
+ return id.ID, response.Process(&id)
+}
diff --git a/pkg/bindings/images/search.go b/pkg/bindings/images/search.go
index 58b25425b..183ff3d77 100644
--- a/pkg/bindings/images/search.go
+++ b/pkg/bindings/images/search.go
@@ -3,6 +3,7 @@ package images
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod/image"
@@ -16,21 +17,21 @@ func Search(ctx context.Context, term string, limit *int, filters map[string][]s
var (
searchResults []image.SearchResult
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
- params["term"] = term
+ params := url.Values{}
+ params.Set("term", term)
if limit != nil {
- params["limit"] = strconv.Itoa(*limit)
+ params.Set("limit", strconv.Itoa(*limit))
}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params)
if err != nil {
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index 97bbb8c42..c95b22953 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -10,7 +10,7 @@ import (
func Create() {}
func Inspect(ctx context.Context, nameOrID string) (map[string]interface{}, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
@@ -23,7 +23,7 @@ func Inspect(ctx context.Context, nameOrID string) (map[string]interface{}, erro
}
func Remove(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -38,7 +38,7 @@ func List(ctx context.Context) ([]*libcni.NetworkConfigList, error) {
var (
netList []*libcni.NetworkConfigList
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index d079f01c2..1a8c31be1 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -3,6 +3,7 @@ package pods
import (
"context"
"net/http"
+ "net/url"
"strconv"
"github.com/containers/libpod/libpod"
@@ -16,7 +17,7 @@ func CreatePod() error {
// Exists is a lightweight method to determine if a pod exists in local storage
func Exists(ctx context.Context, nameOrID string) (bool, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return false, err
}
@@ -29,7 +30,7 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
// Inspect returns low-level information about the given pod.
func Inspect(ctx context.Context, nameOrID string) (*libpod.PodInspect, error) {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
@@ -44,13 +45,13 @@ func Inspect(ctx context.Context, nameOrID string) (*libpod.PodInspect, error) {
// Kill sends a SIGTERM to all the containers in a pod. The optional signal parameter
// can be used to override SIGTERM.
func Kill(ctx context.Context, nameOrID string, signal *string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if signal != nil {
- params["signal"] = *signal
+ params.Set("signal", *signal)
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nameOrID)
if err != nil {
@@ -61,7 +62,7 @@ func Kill(ctx context.Context, nameOrID string, signal *string) error {
// Pause pauses all running containers in a given pod.
func Pause(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -74,7 +75,7 @@ func Pause(ctx context.Context, nameOrID string) error {
// Prune removes all non-running pods in local storage.
func Prune(ctx context.Context) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -87,32 +88,32 @@ func Prune(ctx context.Context) error {
// List returns all pods in local storage. The optional filters parameter can
// be used to refine which pods should be listed.
-func List(ctx context.Context, filters map[string][]string) (*[]libpod.PodInspect, error) {
+func List(ctx context.Context, filters map[string][]string) ([]*libpod.PodInspect, error) {
var (
- inspect []libpod.PodInspect
+ inspect []*libpod.PodInspect
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- params := make(map[string]string)
+ params := url.Values{}
if filters != nil {
stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
- params["filters"] = stringFilter
+ params.Set("filters", stringFilter)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/pods/json", params)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params)
if err != nil {
- return &inspect, err
+ return inspect, err
}
- return &inspect, response.Process(&inspect)
+ return inspect, response.Process(&inspect)
}
// Restart restarts all containers in a pod.
func Restart(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
@@ -126,13 +127,13 @@ func Restart(ctx context.Context, nameOrID string) error {
// Remove deletes a Pod from from local storage. The optional force parameter denotes
// that the Pod can be removed even if in a running state.
func Remove(ctx context.Context, nameOrID string, force *bool) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nameOrID)
if err != nil {
@@ -143,11 +144,11 @@ func Remove(ctx context.Context, nameOrID string, force *bool) error {
// Start starts all containers in a pod.
func Start(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s/start", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/start", nil, nameOrID)
if err != nil {
return err
}
@@ -162,13 +163,13 @@ func Stats() error {
// Stop stops all containers in a Pod. The optional timeout parameter can be
// used to override the timeout before the container is killed.
func Stop(ctx context.Context, nameOrID string, timeout *int) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if timeout != nil {
- params["t"] = strconv.Itoa(*timeout)
+ params.Set("t", strconv.Itoa(*timeout))
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nameOrID)
if err != nil {
@@ -184,7 +185,7 @@ func Top() error {
// Unpause unpauses all paused containers in a Pod.
func Unpause(ctx context.Context, nameOrID string) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index dba94cb35..38f5014ca 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -20,9 +20,18 @@ type testImage struct {
}
const (
+ devPodmanBinaryLocation string = "../../../bin/podman"
defaultPodmanBinaryLocation string = "/usr/bin/podman"
)
+func getPodmanBinary() string {
+ _, err := os.Stat(devPodmanBinaryLocation)
+ if os.IsNotExist(err) {
+ return defaultPodmanBinaryLocation
+ }
+ return devPodmanBinaryLocation
+}
+
var (
ImageCacheDir = "/tmp/podman/imagecachedir"
LockTmpDir string
@@ -50,7 +59,7 @@ type bindingTest struct {
func (b *bindingTest) runPodman(command []string) *gexec.Session {
var cmd []string
- podmanBinary := defaultPodmanBinaryLocation
+ podmanBinary := getPodmanBinary()
val, ok := os.LookupEnv("PODMAN_BINARY")
if ok {
podmanBinary = val
@@ -114,7 +123,7 @@ func newBindingTest() *bindingTest {
runRoot: filepath.Join(tmpPath, "run"),
artifactDirPath: "",
imageCacheDir: "",
- sock: fmt.Sprintf("unix:%s", filepath.Join(tmpPath, "api.sock")),
+ sock: fmt.Sprintf("unix://%s", filepath.Join(tmpPath, "api.sock")),
tempDirPath: tmpPath,
}
return &b
@@ -162,16 +171,30 @@ func (b *bindingTest) restoreImageFromCache(i testImage) {
p.Wait(45)
}
-// Run a container and add append the alpine image to it
-func (b *bindingTest) RunTopContainer(name *string) {
+// Run a container within or without a pod
+// and add or append the alpine image to it
+func (b *bindingTest) RunTopContainer(containerName *string, insidePod *bool, podName *string) {
cmd := []string{"run", "-dt"}
- if name != nil {
- containerName := *name
- cmd = append(cmd, "--name", containerName)
+ if insidePod != nil && podName != nil {
+ pName := *podName
+ cmd = append(cmd, "--pod", pName)
+ } else if containerName != nil {
+ cName := *containerName
+ cmd = append(cmd, "--name", cName)
}
cmd = append(cmd, alpine.name, "top")
- p := b.runPodman(cmd)
- p.Wait(45)
+ b.runPodman(cmd).Wait(45)
+}
+
+// This method creates a pod with the given pod name.
+// Podname is an optional parameter
+func (b *bindingTest) Podcreate(name *string) {
+ if name != nil {
+ podname := *name
+ b.runPodman([]string{"pod", "create", "--name", podname}).Wait(45)
+ } else {
+ b.runPodman([]string{"pod", "create"}).Wait(45)
+ }
}
// StringInSlice returns a boolean based on whether a given
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
new file mode 100644
index 000000000..6756e81c7
--- /dev/null
+++ b/pkg/bindings/test/containers_test.go
@@ -0,0 +1,253 @@
+package test_bindings
+
+import (
+ "context"
+ "net/http"
+ "strconv"
+ "time"
+
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/bindings/containers"
+ "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman containers ", func() {
+ var (
+ bt *bindingTest
+ s *gexec.Session
+ connText context.Context
+ err error
+ falseFlag bool = false
+ trueFlag bool = true
+ )
+
+ BeforeEach(func() {
+ bt = newBindingTest()
+ bt.RestoreImagesFromCache()
+ s = bt.startAPIService()
+ time.Sleep(1 * time.Second)
+ connText, err = bindings.NewConnection(context.Background(), bt.sock)
+ Expect(err).To(BeNil())
+ })
+
+ AfterEach(func() {
+ s.Kill()
+ bt.cleanup()
+ })
+
+ It("podman pause a bogus container", func() {
+ // Pausing bogus container should return 404
+ err = containers.Pause(connText, "foobar")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+ })
+
+ It("podman unpause a bogus container", func() {
+ // Unpausing bogus container should return 404
+ err = containers.Unpause(connText, "foobar")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+ })
+
+ It("podman pause a running container by name", func() {
+ // Pausing by name should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Pause(connText, name)
+ Expect(err).To(BeNil())
+
+ // Ensure container is paused
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.State.Status).To(Equal("paused"))
+ })
+
+ It("podman pause a running container by id", func() {
+ // Pausing by id should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).To(BeNil())
+
+ // Ensure container is paused
+ data, err = containers.Inspect(connText, data.ID, nil)
+ Expect(data.State.Status).To(Equal("paused"))
+ })
+
+ It("podman unpause a running container by name", func() {
+ // Unpausing by name should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Pause(connText, name)
+ Expect(err).To(BeNil())
+ err = containers.Unpause(connText, name)
+ Expect(err).To(BeNil())
+
+ // Ensure container is unpaused
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(data.State.Status).To(Equal("running"))
+ })
+
+ It("podman unpause a running container by ID", func() {
+ // Unpausing by ID should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ // Pause by name
+ err := containers.Pause(connText, name)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Unpause(connText, data.ID)
+ Expect(err).To(BeNil())
+
+ // Ensure container is unpaused
+ data, err = containers.Inspect(connText, name, nil)
+ Expect(data.State.Status).To(Equal("running"))
+ })
+
+ It("podman pause a paused container by name", func() {
+ // Pausing a paused container by name should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Pause(connText, name)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, name)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman pause a paused container by id", func() {
+ // Pausing a paused container by id should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman pause a stopped container by name", func() {
+ // Pausing a stopped container by name should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Stop(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, name)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman pause a stopped container by id", func() {
+ // Pausing a stopped container by id should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ err = containers.Stop(connText, data.ID, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman remove a paused container by id without force", func() {
+ // Removing a paused container without force should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).To(BeNil())
+ err = containers.Remove(connText, data.ID, &falseFlag, &falseFlag)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman remove a paused container by id with force", func() {
+ // FIXME: Skip on F31 and later
+ host := utils.GetHostDistributionInfo()
+ osVer, err := strconv.Atoi(host.Version)
+ Expect(err).To(BeNil())
+ if host.Distribution == "fedora" && osVer >= 31 {
+ Skip("FIXME: https://github.com/containers/libpod/issues/5325")
+ }
+
+ // Removing a paused container with force should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).To(BeNil())
+ err = containers.Remove(connText, data.ID, &trueFlag, &falseFlag)
+ Expect(err).To(BeNil())
+ })
+
+ It("podman stop a paused container by name", func() {
+ // Stopping a paused container by name should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Pause(connText, name)
+ Expect(err).To(BeNil())
+ err = containers.Stop(connText, name, nil)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman stop a paused container by id", func() {
+ // Stopping a paused container by id should fail
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Pause(connText, data.ID)
+ Expect(err).To(BeNil())
+ err = containers.Stop(connText, data.ID, nil)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("podman stop a running container by name", func() {
+ // Stopping a running container by name should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ err := containers.Stop(connText, name, nil)
+ Expect(err).To(BeNil())
+
+ // Ensure container is stopped
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.State.Status).To(Equal("exited"))
+ })
+
+ It("podman stop a running container by ID", func() {
+ // Stopping a running container by ID should work
+ var name = "top"
+ bt.RunTopContainer(&name, &falseFlag, nil)
+ data, err := containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ err = containers.Stop(connText, data.ID, nil)
+ Expect(err).To(BeNil())
+
+ // Ensure container is stopped
+ data, err = containers.Inspect(connText, name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.State.Status).To(Equal("exited"))
+ })
+
+})
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 74e0cc67a..8eef28502 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -3,6 +3,8 @@ package test_bindings
import (
"context"
"net/http"
+ "os"
+ "path/filepath"
"time"
"github.com/containers/libpod/pkg/bindings"
@@ -38,7 +40,7 @@ var _ = Describe("Podman images", func() {
bt.RestoreImagesFromCache()
s = bt.startAPIService()
time.Sleep(1 * time.Second)
- connText, err = bindings.NewConnection(bt.sock)
+ connText, err = bindings.NewConnection(context.Background(), bt.sock)
Expect(err).To(BeNil())
})
@@ -71,6 +73,14 @@ var _ = Describe("Podman images", func() {
// Inspect by long name
_, err = images.GetImage(connText, alpine.name, nil)
Expect(err).To(BeNil())
+ // TODO it looks like the images API alwaays returns size regardless
+ // of bool or not. What should we do ?
+ //Expect(data.Size).To(BeZero())
+
+ // Enabling the size parameter should result in size being populated
+ data, err = images.GetImage(connText, alpine.name, &trueFlag)
+ Expect(err).To(BeNil())
+ Expect(data.Size).To(BeNumerically(">", 0))
})
// Test to validate the remove image api
@@ -93,7 +103,7 @@ var _ = Describe("Podman images", func() {
// Start a container with alpine image
var top string = "top"
- bt.RunTopContainer(&top)
+ bt.RunTopContainer(&top, &falseFlag, nil)
// we should now have a container called "top" running
containerResponse, err := containers.Inspect(connText, "top", &falseFlag)
Expect(err).To(BeNil())
@@ -181,4 +191,159 @@ var _ = Describe("Podman images", func() {
Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
})
+ It("Image Exists", func() {
+ // exists on bogus image should be false, with no error
+ exists, err := images.Exists(connText, "foobar")
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+
+ // exists with shortname should be true
+ exists, err = images.Exists(connText, alpine.shortName)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // exists with fqname should be true
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+ })
+
+ It("Load|Import Image", func() {
+ // load an image
+ _, err := images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err := images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ f, err := os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ defer f.Close()
+ Expect(err).To(BeNil())
+ names, err := images.Load(connText, f, nil)
+ Expect(err).To(BeNil())
+ Expect(names).To(Equal(alpine.name))
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // load with a repo name
+ f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ Expect(err).To(BeNil())
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ newName := "quay.io/newname:fizzle"
+ names, err = images.Load(connText, f, &newName)
+ Expect(err).To(BeNil())
+ Expect(names).To(Equal(alpine.name))
+ exists, err = images.Exists(connText, newName)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // load with a bad repo name should trigger a 500
+ f, err = os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ Expect(err).To(BeNil())
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ badName := "quay.io/newName:fizzle"
+ _, err = images.Load(connText, f, &badName)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("Export Image", func() {
+ // Export an image
+ exportPath := filepath.Join(bt.tempDirPath, alpine.tarballName)
+ w, err := os.Create(filepath.Join(bt.tempDirPath, alpine.tarballName))
+ defer w.Close()
+ Expect(err).To(BeNil())
+ err = images.Export(connText, alpine.name, w, nil, nil)
+ Expect(err).To(BeNil())
+ _, err = os.Stat(exportPath)
+ Expect(err).To(BeNil())
+
+ // TODO how do we verify that a format change worked?
+ })
+
+ It("Import Image", func() {
+ // load an image
+ _, err = images.Remove(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ exists, err := images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeFalse())
+ f, err := os.Open(filepath.Join(ImageCacheDir, alpine.tarballName))
+ defer f.Close()
+ Expect(err).To(BeNil())
+ changes := []string{"CMD /bin/foobar"}
+ testMessage := "test_import"
+ _, err = images.Import(connText, changes, &testMessage, &alpine.name, nil, f)
+ Expect(err).To(BeNil())
+ exists, err = images.Exists(connText, alpine.name)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+ data, err := images.GetImage(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ Expect(data.Comment).To(Equal(testMessage))
+
+ })
+ It("History Image", func() {
+ // a bogus name should return a 404
+ _, err := images.History(connText, "foobar")
+ Expect(err).To(Not(BeNil()))
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ var foundID bool
+ data, err := images.GetImage(connText, alpine.name, nil)
+ Expect(err).To(BeNil())
+ history, err := images.History(connText, alpine.name)
+ Expect(err).To(BeNil())
+ for _, i := range history {
+ if i.ID == data.ID {
+ foundID = true
+ break
+ }
+ }
+ Expect(foundID).To(BeTrue())
+ })
+
+ It("Search for an image", func() {
+ imgs, err := images.Search(connText, "alpine", nil, nil)
+ Expect(err).To(BeNil())
+ Expect(len(imgs)).To(BeNumerically(">", 1))
+ var foundAlpine bool
+ for _, i := range imgs {
+ if i.Name == "docker.io/library/alpine" {
+ foundAlpine = true
+ break
+ }
+ }
+ Expect(foundAlpine).To(BeTrue())
+
+ // Search for alpine with a limit of 10
+ ten := 10
+ imgs, err = images.Search(connText, "docker.io/alpine", &ten, nil)
+ Expect(err).To(BeNil())
+ Expect(len(imgs)).To(BeNumerically("<=", 10))
+
+ // Search for alpine with stars greater than 100
+ filters := make(map[string][]string)
+ filters["stars"] = []string{"100"}
+ imgs, err = images.Search(connText, "docker.io/alpine", nil, filters)
+ Expect(err).To(BeNil())
+ for _, i := range imgs {
+ Expect(i.Stars).To(BeNumerically(">=", 100))
+ }
+
+ // Search with a fqdn
+ imgs, err = images.Search(connText, "quay.io/libpod/alpine_nginx", nil, nil)
+ Expect(len(imgs)).To(BeNumerically(">=", 1))
+ })
+
})
diff --git a/pkg/bindings/test/pods_test.go b/pkg/bindings/test/pods_test.go
new file mode 100644
index 000000000..4bea2f8d7
--- /dev/null
+++ b/pkg/bindings/test/pods_test.go
@@ -0,0 +1,196 @@
+package test_bindings
+
+import (
+ "context"
+ "net/http"
+ "time"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/bindings/pods"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman images", func() {
+ var (
+ bt *bindingTest
+ s *gexec.Session
+ connText context.Context
+ newpod string
+ err error
+ trueFlag bool = true
+ )
+
+ BeforeEach(func() {
+ bt = newBindingTest()
+ newpod = "newpod"
+ bt.RestoreImagesFromCache()
+ bt.Podcreate(&newpod)
+ s = bt.startAPIService()
+ time.Sleep(1 * time.Second)
+ connText, err = bindings.NewConnection(context.Background(), bt.sock)
+ Expect(err).To(BeNil())
+ })
+
+ AfterEach(func() {
+ s.Kill()
+ bt.cleanup()
+ })
+
+ It("inspect pod", func() {
+ //Inspect an invalid pod name
+ _, err := pods.Inspect(connText, "dummyname")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ //Inspect an valid pod name
+ response, err := pods.Inspect(connText, newpod)
+ Expect(err).To(BeNil())
+ Expect(response.Config.Name).To(Equal(newpod))
+ })
+
+ // Test validates the list all api returns
+ It("list pod", func() {
+ //List all the pods in the current instance
+ podSummary, err := pods.List(connText, nil)
+ Expect(err).To(BeNil())
+ Expect(len(podSummary)).To(Equal(1))
+ // Adding an alpine container to the existing pod
+ bt.RunTopContainer(nil, &trueFlag, &newpod)
+ podSummary, err = pods.List(connText, nil)
+ // Verify no errors.
+ Expect(err).To(BeNil())
+ // Verify number of containers in the pod.
+ Expect(len(podSummary[0].Containers)).To(Equal(2))
+
+ // Add multiple pods and verify them by name and size.
+ var newpod2 string = "newpod2"
+ bt.Podcreate(&newpod2)
+ podSummary, err = pods.List(connText, nil)
+ Expect(len(podSummary)).To(Equal(2))
+ var names []string
+ for _, i := range podSummary {
+ names = append(names, i.Config.Name)
+ }
+ Expect(StringInSlice(newpod, names)).To(BeTrue())
+ Expect(StringInSlice("newpod2", names)).To(BeTrue())
+
+ // TODO not working Because: code to list based on filter
+ // "not yet implemented",
+ // Validate list pod with filters
+ //filters := make(map[string][]string)
+ //filters["name"] = []string{newpod}
+ //filteredPods, err := pods.List(connText, filters)
+ //Expect(err).To(BeNil())
+ //Expect(len(filteredPods)).To(BeNumerically("==", 1))
+ })
+
+ // The test validates if the exists responds
+ It("exists pod", func() {
+ response, err := pods.Exists(connText, "dummyName")
+ Expect(err).To(BeNil())
+ Expect(response).To(BeFalse())
+
+ // Should exit with no error and response should be true
+ response, err = pods.Exists(connText, "newpod")
+ Expect(err).To(BeNil())
+ Expect(response).To(BeTrue())
+ })
+
+ // This test validates if All running containers within
+ // each specified pod are paused and unpaused
+ It("pause upause pod", func() {
+ // Pause invalid container
+ err := pods.Pause(connText, "dummyName")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // Adding an alpine container to the existing pod
+ bt.RunTopContainer(nil, &trueFlag, &newpod)
+ response, err := pods.Inspect(connText, newpod)
+ Expect(err).To(BeNil())
+
+ // Binding needs to be modified to inspect the pod state.
+ // Since we dont have a pod state we inspect the states of the containers within the pod.
+ // Pause a valid container
+ err = pods.Pause(connText, newpod)
+ Expect(err).To(BeNil())
+ response, err = pods.Inspect(connText, newpod)
+ for _, i := range response.Containers {
+ Expect(define.StringToContainerStatus(i.State)).
+ To(Equal(define.ContainerStatePaused))
+ }
+
+ // Unpause a valid container
+ err = pods.Unpause(connText, newpod)
+ Expect(err).To(BeNil())
+ response, err = pods.Inspect(connText, newpod)
+ for _, i := range response.Containers {
+ Expect(define.StringToContainerStatus(i.State)).
+ To(Equal(define.ContainerStateRunning))
+ }
+ })
+
+ It("start stop restart pod", func() {
+ // Start an invalid pod
+ err = pods.Start(connText, "dummyName")
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // Stop an invalid pod
+ err = pods.Stop(connText, "dummyName", nil)
+ Expect(err).ToNot(BeNil())
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // Restart an invalid pod
+ err = pods.Restart(connText, "dummyName")
+ Expect(err).ToNot(BeNil())
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // Start a valid pod and inspect status of each container
+ err = pods.Start(connText, newpod)
+ Expect(err).To(BeNil())
+
+ response, err := pods.Inspect(connText, newpod)
+ for _, i := range response.Containers {
+ Expect(define.StringToContainerStatus(i.State)).
+ To(Equal(define.ContainerStateRunning))
+ }
+
+ // Start an already running pod
+ err = pods.Start(connText, newpod)
+ Expect(err).To(BeNil())
+
+ // Stop the running pods
+ err = pods.Stop(connText, newpod, nil)
+ Expect(err).To(BeNil())
+ response, _ = pods.Inspect(connText, newpod)
+ for _, i := range response.Containers {
+ Expect(define.StringToContainerStatus(i.State)).
+ To(Equal(define.ContainerStateStopped))
+ }
+
+ // Stop an already stopped pod
+ err = pods.Stop(connText, newpod, nil)
+ Expect(err).To(BeNil())
+
+ err = pods.Restart(connText, newpod)
+ Expect(err).To(BeNil())
+ response, _ = pods.Inspect(connText, newpod)
+ for _, i := range response.Containers {
+ Expect(define.StringToContainerStatus(i.State)).
+ To(Equal(define.ContainerStateRunning))
+ }
+ })
+
+ // Remove all stopped pods and their container to be implemented.
+ It("prune pod", func() {
+ })
+})
diff --git a/pkg/bindings/test/volumes_test.go b/pkg/bindings/test/volumes_test.go
new file mode 100644
index 000000000..c8940d46e
--- /dev/null
+++ b/pkg/bindings/test/volumes_test.go
@@ -0,0 +1,174 @@
+package test_bindings
+
+import (
+ "context"
+ "fmt"
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/bindings/containers"
+ "github.com/containers/libpod/pkg/bindings/volumes"
+ "net/http"
+ "time"
+
+ "github.com/containers/libpod/pkg/bindings"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman volumes", func() {
+ var (
+ //tempdir string
+ //err error
+ //podmanTest *PodmanTestIntegration
+ bt *bindingTest
+ s *gexec.Session
+ connText context.Context
+ err error
+ trueFlag = true
+ )
+
+ BeforeEach(func() {
+ //tempdir, err = CreateTempDirInTempDir()
+ //if err != nil {
+ // os.Exit(1)
+ //}
+ //podmanTest = PodmanTestCreate(tempdir)
+ //podmanTest.Setup()
+ //podmanTest.SeedImages()
+ bt = newBindingTest()
+ bt.RestoreImagesFromCache()
+ s = bt.startAPIService()
+ time.Sleep(1 * time.Second)
+ connText, err = bindings.NewConnection(context.Background(), bt.sock)
+ Expect(err).To(BeNil())
+ })
+
+ AfterEach(func() {
+ //podmanTest.Cleanup()
+ //f := CurrentGinkgoTestDescription()
+ //processTestResult(f)
+ s.Kill()
+ bt.cleanup()
+ })
+
+ It("create volume", func() {
+ // create a volume with blank config should work
+ _, err := volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+
+ vcc := handlers.VolumeCreateConfig{
+ Name: "foobar",
+ Label: nil,
+ Opts: nil,
+ }
+ vol, err := volumes.Create(connText, vcc)
+ Expect(err).To(BeNil())
+ Expect(vol.Name).To(Equal("foobar"))
+
+ // create volume with same name should 500
+ _, err = volumes.Create(connText, vcc)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+ })
+
+ It("inspect volume", func() {
+ vol, err := volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+ data, err := volumes.Inspect(connText, vol.Name)
+ Expect(err).To(BeNil())
+ Expect(data.Name).To(Equal(vol.Name))
+ })
+
+ It("remove volume", func() {
+ // removing a bogus volume should result in 404
+ err := volumes.Remove(connText, "foobar", nil)
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusNotFound))
+
+ // Removing an unused volume should work
+ vol, err := volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+ err = volumes.Remove(connText, vol.Name, nil)
+ Expect(err).To(BeNil())
+
+ // Removing a volume that is being used without force should be 409
+ vol, err = volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+ session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/foobar", vol.Name), "--name", "vtest", alpine.name, "top"})
+ session.Wait(45)
+ err = volumes.Remove(connText, vol.Name, nil)
+ Expect(err).ToNot(BeNil())
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusConflict))
+
+ // Removing with a volume in use with force should work with a stopped container
+ zero := 0
+ err = containers.Stop(connText, "vtest", &zero)
+ Expect(err).To(BeNil())
+ err = volumes.Remove(connText, vol.Name, &trueFlag)
+ Expect(err).To(BeNil())
+ })
+
+ It("list volumes", func() {
+ // no volumes should be ok
+ vols, err := volumes.List(connText, nil)
+ Expect(err).To(BeNil())
+ Expect(len(vols)).To(BeZero())
+
+ // create a bunch of named volumes and make verify with list
+ volNames := []string{"homer", "bart", "lisa", "maggie", "marge"}
+ for i := 0; i < 5; i++ {
+ _, err = volumes.Create(connText, handlers.VolumeCreateConfig{Name: volNames[i]})
+ Expect(err).To(BeNil())
+ }
+ vols, err = volumes.List(connText, nil)
+ Expect(err).To(BeNil())
+ Expect(len(vols)).To(BeNumerically("==", 5))
+ for _, v := range vols {
+ Expect(StringInSlice(v.Name, volNames)).To(BeTrue())
+ }
+
+ // list with bad filter should be 500
+ filters := make(map[string][]string)
+ filters["foobar"] = []string{"1234"}
+ _, err = volumes.List(connText, filters)
+ Expect(err).ToNot(BeNil())
+ code, _ := bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
+
+ filters = make(map[string][]string)
+ filters["name"] = []string{"homer"}
+ vols, err = volumes.List(connText, filters)
+ Expect(err).To(BeNil())
+ Expect(len(vols)).To(BeNumerically("==", 1))
+ Expect(vols[0].Name).To(Equal("homer"))
+ })
+
+ // TODO we need to add filtering to tests
+ It("prune unused volume", func() {
+ // Pruning when no volumes present should be ok
+ _, err := volumes.Prune(connText)
+ Expect(err).To(BeNil())
+
+ // Removing an unused volume should work
+ _, err = volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+ vols, err := volumes.Prune(connText)
+ Expect(err).To(BeNil())
+ Expect(len(vols)).To(BeNumerically("==", 1))
+
+ _, err = volumes.Create(connText, handlers.VolumeCreateConfig{Name: "homer"})
+ Expect(err).To(BeNil())
+ _, err = volumes.Create(connText, handlers.VolumeCreateConfig{})
+ Expect(err).To(BeNil())
+ session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/homer", "homer"), "--name", "vtest", alpine.name, "top"})
+ session.Wait(45)
+ vols, err = volumes.Prune(connText)
+ Expect(err).To(BeNil())
+ Expect(len(vols)).To(BeNumerically("==", 1))
+ _, err = volumes.Inspect(connText, "homer")
+ Expect(err).To(BeNil())
+ })
+
+})
diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go
index 05a4f73fd..0bc818605 100644
--- a/pkg/bindings/volumes/volumes.go
+++ b/pkg/bindings/volumes/volumes.go
@@ -3,28 +3,35 @@ package volumes
import (
"context"
"net/http"
+ "net/url"
"strconv"
+ "strings"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
+ jsoniter "github.com/json-iterator/go"
)
// Create creates a volume given its configuration.
-func Create(ctx context.Context, config handlers.VolumeCreateConfig) (string, error) {
- // TODO This is incomplete. The config needs to be sent via the body
+func Create(ctx context.Context, config handlers.VolumeCreateConfig) (*libpod.VolumeConfig, error) {
var (
- volumeID string
+ v libpod.VolumeConfig
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
- return "", err
+ return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/create", nil)
+ createString, err := jsoniter.MarshalToString(config)
if err != nil {
- return volumeID, err
+ return nil, err
}
- return volumeID, response.Process(&volumeID)
+ stringReader := strings.NewReader(createString)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/volumes/create", nil)
+ if err != nil {
+ return nil, err
+ }
+ return &v, response.Process(&v)
}
// Inspect returns low-level information about a volume.
@@ -32,22 +39,40 @@ func Inspect(ctx context.Context, nameOrID string) (*libpod.InspectVolumeData, e
var (
inspect libpod.InspectVolumeData
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/%s/json", nil, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/%s/json", nil, nameOrID)
if err != nil {
return &inspect, err
}
return &inspect, response.Process(&inspect)
}
-func List() error {
- // TODO
- // The API side of things for this one does a lot in main and therefore
- // is not implemented yet.
- return bindings.ErrNotImplemented // nolint:typecheck
+// List returns the configurations for existing volumes in the form of a slice. Optionally, filters
+// can be used to refine the list of volumes.
+func List(ctx context.Context, filters map[string][]string) ([]*libpod.VolumeConfig, error) {
+ var (
+ vols []*libpod.VolumeConfig
+ )
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ if len(filters) > 0 {
+ strFilters, err := bindings.FiltersToString(filters)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("filters", strFilters)
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/json", params)
+ if err != nil {
+ return vols, err
+ }
+ return vols, response.Process(&vols)
}
// Prune removes unused volumes from the local filesystem.
@@ -55,7 +80,7 @@ func Prune(ctx context.Context) ([]string, error) {
var (
pruned []string
)
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
@@ -69,15 +94,15 @@ func Prune(ctx context.Context) ([]string, error) {
// Remove deletes the given volume from storage. The optional force parameter
// is used to remove a volume even if it is being used by a container.
func Remove(ctx context.Context, nameOrID string, force *bool) error {
- conn, err := bindings.GetConnectionFromContext(ctx)
+ conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
- params := make(map[string]string)
+ params := url.Values{}
if force != nil {
- params["force"] = strconv.FormatBool(*force)
+ params.Set("force", strconv.FormatBool(*force))
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/%s/prune", params, nameOrID)
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/volumes/%s", params, nameOrID)
if err != nil {
return err
}
diff --git a/pkg/network/netconflist.go b/pkg/network/netconflist.go
index a8217097a..34ff00024 100644
--- a/pkg/network/netconflist.go
+++ b/pkg/network/netconflist.go
@@ -110,7 +110,6 @@ func NewPortMapPlugin() PortMapConfig {
func NewFirewallPlugin() FirewallConfig {
return FirewallConfig{
PluginType: "firewall",
- Backend: "iptables",
}
}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 83f4f3254..db898e706 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -58,7 +58,7 @@ static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
static int open_files_max_fd;
-fd_set open_files_set;
+static fd_set *open_files_set;
static uid_t rootless_uid_init;
static gid_t rootless_gid_init;
@@ -240,17 +240,39 @@ static void __attribute__((constructor)) init()
if (d)
{
struct dirent *ent;
+ size_t size = 0;
- FD_ZERO (&open_files_set);
for (ent = readdir (d); ent; ent = readdir (d))
{
- int fd = atoi (ent->d_name);
- if (fd != dirfd (d))
+ int fd;
+
+ if (ent->d_name[0] == '.')
+ continue;
+
+ fd = atoi (ent->d_name);
+ if (fd == dirfd (d))
+ continue;
+
+ if (fd >= size * FD_SETSIZE)
{
- if (fd > open_files_max_fd)
- open_files_max_fd = fd;
- FD_SET (fd, &open_files_set);
+ int i;
+ size_t new_size;
+
+ new_size = (fd / FD_SETSIZE) + 1;
+ open_files_set = realloc (open_files_set, new_size * sizeof (fd_set));
+ if (open_files_set == NULL)
+ _exit (EXIT_FAILURE);
+
+ for (i = size; i < new_size; i++)
+ FD_ZERO (&(open_files_set[i]));
+
+ size = new_size;
}
+
+ if (fd > open_files_max_fd)
+ open_files_max_fd = fd;
+
+ FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE]));
}
closedir (d);
}
@@ -553,10 +575,8 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path)
/* We passed down these fds, close them. */
int f;
for (f = 3; f < open_files_max_fd; f++)
- {
- if (FD_ISSET (f, &open_files_set))
- close (f);
- }
+ if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
+ close (f);
return pid;
}
@@ -747,10 +767,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
num_fds = strtol (listen_fds, NULL, 10);
if (num_fds != LONG_MIN && num_fds != LONG_MAX)
{
- long i;
- for (i = 3; i < num_fds + 3; i++)
- if (FD_ISSET (i, &open_files_set))
- close (i);
+ int f;
+
+ for (f = 3; f < num_fds + 3; f++)
+ if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
+ close (f);
}
unsetenv ("LISTEN_PID");
unsetenv ("LISTEN_FDS");
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index f71d55776..5ddfab7ad 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -510,7 +510,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st
}
}
}
- if !foundProcess {
+ if !foundProcess && pausePidPath != "" {
return BecomeRootInUserNS(pausePidPath)
}
if lastErr != nil {
diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go
index dcf255378..eeba46a72 100644
--- a/pkg/seccomp/seccomp.go
+++ b/pkg/seccomp/seccomp.go
@@ -6,7 +6,7 @@ import (
"github.com/pkg/errors"
)
-// ContianerImageLabel is the key of the image annotation embedding a seccomp
+// ContainerImageLabel is the key of the image annotation embedding a seccomp
// profile.
const ContainerImageLabel = "io.containers.seccomp.profile"
diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
index 5f39b6d0d..544c0020d 100644
--- a/pkg/spec/config_linux.go
+++ b/pkg/spec/config_linux.go
@@ -32,8 +32,8 @@ func Device(d *configs.Device) spec.LinuxDevice {
}
}
-// devicesFromPath computes a list of devices
-func devicesFromPath(g *generate.Generator, devicePath string) error {
+// DevicesFromPath computes a list of devices
+func DevicesFromPath(g *generate.Generator, devicePath string) error {
devs := strings.Split(devicePath, ":")
resolvedDevicePath := devs[0]
// check if it is a symbolic link
@@ -216,7 +216,7 @@ func getDevices(path string) ([]*configs.Device, error) {
return out, nil
}
-func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
+func addPrivilegedDevices(g *generate.Generator) error {
hostDevices, err := getDevices("/dev")
if err != nil {
return err
@@ -280,16 +280,16 @@ func (c *CreateConfig) createBlockIO() (*spec.LinuxBlockIO, error) {
var lwds []spec.LinuxWeightDevice
ret = bio
for _, i := range c.Resources.BlkioWeightDevice {
- wd, err := validateweightDevice(i)
+ wd, err := ValidateweightDevice(i)
if err != nil {
return ret, errors.Wrapf(err, "invalid values for blkio-weight-device")
}
- wdStat, err := getStatFromPath(wd.path)
+ wdStat, err := GetStatFromPath(wd.Path)
if err != nil {
- return ret, errors.Wrapf(err, "error getting stat from path %q", wd.path)
+ return ret, errors.Wrapf(err, "error getting stat from path %q", wd.Path)
}
lwd := spec.LinuxWeightDevice{
- Weight: &wd.weight,
+ Weight: &wd.Weight,
}
lwd.Major = int64(unix.Major(wdStat.Rdev))
lwd.Minor = int64(unix.Minor(wdStat.Rdev))
@@ -347,7 +347,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
if err != nil {
return []spec.LinuxThrottleDevice{}, err
}
- ltdStat, err := getStatFromPath(t.path)
+ ltdStat, err := GetStatFromPath(t.path)
if err != nil {
return ltds, errors.Wrapf(err, "error getting stat from path %q", t.path)
}
@@ -361,7 +361,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
return ltds, nil
}
-func getStatFromPath(path string) (unix.Stat_t, error) {
+func GetStatFromPath(path string) (unix.Stat_t, error) {
s := unix.Stat_t{}
err := unix.Stat(path, &s)
return s, err
diff --git a/pkg/spec/config_unsupported.go b/pkg/spec/config_unsupported.go
index be3e7046d..568afde55 100644
--- a/pkg/spec/config_unsupported.go
+++ b/pkg/spec/config_unsupported.go
@@ -15,7 +15,7 @@ func addDevice(g *generate.Generator, device string) error {
return errors.New("function not implemented")
}
-func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
+func addPrivilegedDevices(g *generate.Generator) error {
return errors.New("function not implemented")
}
@@ -27,7 +27,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
return nil, errors.New("function not implemented")
}
-func devicesFromPath(g *generate.Generator, devicePath string) error {
+func DevicesFromPath(g *generate.Generator, devicePath string) error {
return errors.New("function not implemented")
}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 8010be0d4..02678a687 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -126,6 +126,7 @@ type SecurityConfig struct {
}
// CreateConfig is a pre OCI spec structure. It represents user input from varlink or the CLI
+// swagger:model CreateConfig
type CreateConfig struct {
Annotations map[string]string
Args []string
@@ -340,9 +341,8 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l
}
options = append(options, nsOpts...)
- useImageVolumes := c.ImageVolumeType == TypeBind
// Gather up the options for NewContainer which consist of With... funcs
- options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image, useImageVolumes))
+ options = append(options, libpod.WithRootFSFromImage(c.ImageID, c.Image))
options = append(options, libpod.WithConmonPidFile(c.ConmonPidFile))
options = append(options, libpod.WithLabels(c.Labels))
options = append(options, libpod.WithShmSize(c.Resources.ShmSize))
@@ -386,6 +386,6 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l
// AddPrivilegedDevices iterates through host devices and adds all
// host devices to the spec
-func (c *CreateConfig) AddPrivilegedDevices(g *generate.Generator) error {
- return c.addPrivilegedDevices(g)
+func AddPrivilegedDevices(g *generate.Generator) error {
+ return addPrivilegedDevices(g)
}
diff --git a/pkg/spec/namespaces.go b/pkg/spec/namespaces.go
index 1f98e6e25..838d95c54 100644
--- a/pkg/spec/namespaces.go
+++ b/pkg/spec/namespaces.go
@@ -422,7 +422,7 @@ func (c *UtsConfig) ConfigureGenerator(g *generate.Generator, net *NetworkConfig
if hostname == "" {
switch {
case utsCtrID != "":
- utsCtr, err := runtime.GetContainer(utsCtrID)
+ utsCtr, err := runtime.LookupContainer(utsCtrID)
if err != nil {
return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", utsCtrID)
}
diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go
index a5dfccdb9..38d93b87f 100644
--- a/pkg/spec/parse.go
+++ b/pkg/spec/parse.go
@@ -19,12 +19,12 @@ const Pod = "pod"
// weightDevice is a structure that holds device:weight pair
type weightDevice struct {
- path string
- weight uint16
+ Path string
+ Weight uint16
}
func (w *weightDevice) String() string {
- return fmt.Sprintf("%s:%d", w.path, w.weight)
+ return fmt.Sprintf("%s:%d", w.Path, w.Weight)
}
// LinuxNS is a struct that contains namespace information
@@ -59,9 +59,9 @@ func NS(s string) string {
return ""
}
-// validateweightDevice validates that the specified string has a valid device-weight format
+// ValidateweightDevice validates that the specified string has a valid device-weight format
// for blkio-weight-device flag
-func validateweightDevice(val string) (*weightDevice, error) {
+func ValidateweightDevice(val string) (*weightDevice, error) {
split := strings.SplitN(val, ":", 2)
if len(split) != 2 {
return nil, fmt.Errorf("bad format: %s", val)
@@ -78,8 +78,8 @@ func validateweightDevice(val string) (*weightDevice, error) {
}
return &weightDevice{
- path: split[0],
- weight: uint16(weight),
+ Path: split[0],
+ Weight: uint16(weight),
}, nil
}
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index b2a152a2d..a4ae22efd 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -16,9 +16,9 @@ import (
"github.com/pkg/errors"
)
-const cpuPeriod = 100000
+const CpuPeriod = 100000
-func getAvailableGids() (int64, error) {
+func GetAvailableGids() (int64, error) {
idMap, err := user.ParseIDMapFile("/proc/self/gid_map")
if err != nil {
return 0, err
@@ -80,7 +80,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
gid5Available := true
if isRootless {
- nGids, err := getAvailableGids()
+ nGids, err := GetAvailableGids()
if err != nil {
return nil, err
}
@@ -197,8 +197,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
addedResources = true
}
if config.Resources.CPUs != 0 {
- g.SetLinuxResourcesCPUPeriod(cpuPeriod)
- g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * cpuPeriod))
+ g.SetLinuxResourcesCPUPeriod(CpuPeriod)
+ g.SetLinuxResourcesCPUQuota(int64(config.Resources.CPUs * CpuPeriod))
addedResources = true
}
if config.Resources.CPURtRuntime != 0 {
@@ -223,12 +223,12 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
// If privileged, we need to add all the host devices to the
// spec. We do not add the user provided ones because we are
// already adding them all.
- if err := config.AddPrivilegedDevices(&g); err != nil {
+ if err := AddPrivilegedDevices(&g); err != nil {
return nil, err
}
} else {
for _, devicePath := range config.Devices {
- if err := devicesFromPath(&g, devicePath); err != nil {
+ if err := DevicesFromPath(&g, devicePath); err != nil {
return nil, err
}
}
@@ -241,23 +241,35 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
// SECURITY OPTS
+ var runtimeConfig *libpodconfig.Config
+
+ if runtime != nil {
+ runtimeConfig, err = runtime.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ }
+
g.SetProcessNoNewPrivileges(config.Security.NoNewPrivs)
if !config.Security.Privileged {
g.SetProcessApparmorProfile(config.Security.ApparmorProfile)
}
- blockAccessToKernelFilesystems(config, &g)
-
- var runtimeConfig *libpodconfig.Config
-
- if runtime != nil {
- runtimeConfig, err = runtime.GetConfig()
- if err != nil {
+ // Unless already set via the CLI, check if we need to disable process
+ // labels or set the defaults.
+ if len(config.Security.LabelOpts) == 0 && runtimeConfig != nil {
+ if !runtimeConfig.EnableLabeling {
+ // Disabled in the config.
+ config.Security.LabelOpts = append(config.Security.LabelOpts, "disable")
+ } else if err := config.Security.SetLabelOpts(runtime, &config.Pid, &config.Ipc); err != nil {
+ // Defaults!
return nil, err
}
}
+ BlockAccessToKernelFilesystems(config.Security.Privileged, config.Pid.PidMode.IsHost(), &g)
+
// RESOURCES - PIDS
if config.Resources.PidsLimit > 0 {
// if running on rootless on a cgroupv1 machine or using the cgroupfs manager, pids
@@ -320,9 +332,9 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
// BIND MOUNTS
- configSpec.Mounts = supercedeUserMounts(userMounts, configSpec.Mounts)
+ configSpec.Mounts = SupercedeUserMounts(userMounts, configSpec.Mounts)
// Process mounts to ensure correct options
- finalMounts, err := initFSMounts(configSpec.Mounts)
+ finalMounts, err := InitFSMounts(configSpec.Mounts)
if err != nil {
return nil, err
}
@@ -404,8 +416,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
return configSpec, nil
}
-func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) {
- if !config.Security.Privileged {
+func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate.Generator) {
+ if !privileged {
for _, mp := range []string{
"/proc/acpi",
"/proc/kcore",
@@ -421,7 +433,7 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator)
g.AddLinuxMaskedPaths(mp)
}
- if config.Pid.PidMode.IsHost() && rootless.IsRootless() {
+ if pidModeIsHost && rootless.IsRootless() {
return
}
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index 0e2098c1d..c365701de 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -739,6 +739,7 @@ func (config *CreateConfig) getImageVolumes() (map[string]spec.Mount, map[string
for vol := range config.BuiltinImgVolumes {
cleanDest := filepath.Clean(vol)
+ logrus.Debugf("Adding image volume at %s", cleanDest)
if config.ImageVolumeType == "tmpfs" {
// Tmpfs image volumes are handled as mounts
mount := spec.Mount{
@@ -747,13 +748,13 @@ func (config *CreateConfig) getImageVolumes() (map[string]spec.Mount, map[string
Type: TypeTmpfs,
Options: []string{"rprivate", "rw", "nodev", "exec"},
}
- mounts[vol] = mount
+ mounts[cleanDest] = mount
} else {
// Anonymous volumes have no name.
namedVolume := new(libpod.ContainerNamedVolume)
namedVolume.Options = []string{"rprivate", "rw", "nodev", "exec"}
namedVolume.Dest = cleanDest
- volumes[vol] = namedVolume
+ volumes[cleanDest] = namedVolume
}
}
@@ -825,7 +826,7 @@ func (config *CreateConfig) addContainerInitBinary(path string) (spec.Mount, err
// TODO: Should we unmount subtree mounts? E.g., if /tmp/ is mounted by
// one mount, and we already have /tmp/a and /tmp/b, should we remove
// the /tmp/a and /tmp/b mounts in favor of the more general /tmp?
-func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount {
+func SupercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.Mount {
if len(mounts) > 0 {
// If we have overlappings mounts, remove them from the spec in favor of
// the user-added volume mounts
@@ -854,7 +855,7 @@ func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.M
}
// Ensure mount options on all mounts are correct
-func initFSMounts(inputMounts []spec.Mount) ([]spec.Mount, error) {
+func InitFSMounts(inputMounts []spec.Mount) ([]spec.Mount, error) {
// We need to look up mounts so we can figure out the proper mount flags
// to apply.
systemMounts, err := pmount.GetMounts()
diff --git a/pkg/specgen/config_linux_cgo.go b/pkg/specgen/config_linux_cgo.go
new file mode 100644
index 000000000..6f547a40d
--- /dev/null
+++ b/pkg/specgen/config_linux_cgo.go
@@ -0,0 +1,62 @@
+// +build linux,cgo
+
+package specgen
+
+import (
+ "context"
+ "io/ioutil"
+
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/seccomp"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/pkg/errors"
+ goSeccomp "github.com/seccomp/containers-golang"
+ "github.com/sirupsen/logrus"
+)
+
+func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec, img *image.Image) (*spec.LinuxSeccomp, error) {
+ var seccompConfig *spec.LinuxSeccomp
+ var err error
+
+ scp, err := seccomp.LookupPolicy(s.SeccompPolicy)
+ if err != nil {
+ return nil, err
+ }
+
+ if scp == seccomp.PolicyImage {
+ labels, err := img.Labels(context.Background())
+ if err != nil {
+ return nil, err
+ }
+ imagePolicy := labels[seccomp.ContainerImageLabel]
+ if len(imagePolicy) < 1 {
+ return nil, errors.New("no seccomp policy defined by image")
+ }
+ logrus.Debug("Loading seccomp profile from the security config")
+ seccompConfig, err = goSeccomp.LoadProfile(imagePolicy, configSpec)
+ if err != nil {
+ return nil, errors.Wrap(err, "loading seccomp profile failed")
+ }
+ return seccompConfig, nil
+ }
+
+ if s.SeccompProfilePath != "" {
+ logrus.Debugf("Loading seccomp profile from %q", s.SeccompProfilePath)
+ seccompProfile, err := ioutil.ReadFile(s.SeccompProfilePath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", s.SeccompProfilePath)
+ }
+ seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec)
+ if err != nil {
+ return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath)
+ }
+ } else {
+ logrus.Debug("Loading default seccomp profile")
+ seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec)
+ if err != nil {
+ return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath)
+ }
+ }
+
+ return seccompConfig, nil
+}
diff --git a/pkg/specgen/config_linux_nocgo.go b/pkg/specgen/config_linux_nocgo.go
new file mode 100644
index 000000000..fc0c58c37
--- /dev/null
+++ b/pkg/specgen/config_linux_nocgo.go
@@ -0,0 +1,11 @@
+// +build linux,!cgo
+
+package specgen
+
+import (
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec) (*spec.LinuxSeccomp, error) {
+ return nil, nil
+}
diff --git a/pkg/specgen/config_unsupported.go b/pkg/specgen/config_unsupported.go
new file mode 100644
index 000000000..5d24ac39c
--- /dev/null
+++ b/pkg/specgen/config_unsupported.go
@@ -0,0 +1,12 @@
+// +build !linux
+
+package specgen
+
+import (
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/pkg/errors"
+)
+
+func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec) (*spec.LinuxSeccomp, error) {
+ return nil, errors.New("function not supported on non-linux OS's")
+}
diff --git a/pkg/specgen/create.go b/pkg/specgen/create.go
new file mode 100644
index 000000000..34f9ffac2
--- /dev/null
+++ b/pkg/specgen/create.go
@@ -0,0 +1,185 @@
+package specgen
+
+import (
+ "context"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/config"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "os"
+)
+
+// MakeContainer creates a container based on the SpecGenerator
+func (s *SpecGenerator) MakeContainer(rt *libpod.Runtime) (*libpod.Container, error) {
+ var pod *libpod.Pod
+ if err := s.validate(rt); err != nil {
+ return nil, errors.Wrap(err, "invalid config provided")
+ }
+ rtc, err := rt.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ options, err := s.createContainerOptions(rt, pod)
+ if err != nil {
+ return nil, err
+ }
+
+ podmanPath, err := os.Executable()
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, s.createExitCommandOption(rtc, podmanPath))
+ newImage, err := rt.ImageRuntime().NewFromLocal(s.Image)
+ if err != nil {
+ return nil, err
+ }
+
+ options = append(options, libpod.WithRootFSFromImage(newImage.ID(), s.Image))
+
+ runtimeSpec, err := s.toOCISpec(rt, newImage)
+ if err != nil {
+ return nil, err
+ }
+ return rt.NewContainer(context.Background(), runtimeSpec, options...)
+}
+
+func (s *SpecGenerator) createContainerOptions(rt *libpod.Runtime, pod *libpod.Pod) ([]libpod.CtrCreateOption, error) {
+ var options []libpod.CtrCreateOption
+ var err error
+
+ if s.Stdin {
+ options = append(options, libpod.WithStdin())
+ }
+ if len(s.Systemd) > 0 {
+ options = append(options, libpod.WithSystemd())
+ }
+ if len(s.Name) > 0 {
+ logrus.Debugf("setting container name %s", s.Name)
+ options = append(options, libpod.WithName(s.Name))
+ }
+ if s.Pod != "" {
+ logrus.Debugf("adding container to pod %s", s.Pod)
+ options = append(options, rt.WithPod(pod))
+ }
+ destinations := []string{}
+ // // Take all mount and named volume destinations.
+ for _, mount := range s.Mounts {
+ destinations = append(destinations, mount.Destination)
+ }
+ for _, volume := range s.Volumes {
+ destinations = append(destinations, volume.Dest)
+ }
+ options = append(options, libpod.WithUserVolumes(destinations))
+
+ if len(s.Volumes) != 0 {
+ options = append(options, libpod.WithNamedVolumes(s.Volumes))
+ }
+
+ if len(s.Command) != 0 {
+ options = append(options, libpod.WithCommand(s.Command))
+ }
+
+ options = append(options, libpod.WithEntrypoint(s.Entrypoint))
+ if s.StopSignal != nil {
+ options = append(options, libpod.WithStopSignal(*s.StopSignal))
+ }
+ if s.StopTimeout != nil {
+ options = append(options, libpod.WithStopTimeout(*s.StopTimeout))
+ }
+ if s.LogConfiguration != nil {
+ if len(s.LogConfiguration.Path) > 0 {
+ options = append(options, libpod.WithLogPath(s.LogConfiguration.Path))
+ }
+ if len(s.LogConfiguration.Options) > 0 && s.LogConfiguration.Options["tag"] != "" {
+ // Note: I'm really guessing here.
+ options = append(options, libpod.WithLogTag(s.LogConfiguration.Options["tag"]))
+ }
+
+ if len(s.LogConfiguration.Driver) > 0 {
+ options = append(options, libpod.WithLogDriver(s.LogConfiguration.Driver))
+ }
+ }
+
+ // Security options
+ if len(s.SelinuxOpts) > 0 {
+ options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
+ }
+ options = append(options, libpod.WithPrivileged(s.Privileged))
+
+ // Get namespace related options
+ namespaceOptions, err := s.generateNamespaceContainerOpts(rt)
+ if err != nil {
+ return nil, err
+ }
+ options = append(options, namespaceOptions...)
+
+ // TODO NetworkNS still needs to be done!
+ if len(s.ConmonPidFile) > 0 {
+ options = append(options, libpod.WithConmonPidFile(s.ConmonPidFile))
+ }
+ options = append(options, libpod.WithLabels(s.Labels))
+ if s.ShmSize != nil {
+ options = append(options, libpod.WithShmSize(*s.ShmSize))
+ }
+ if s.Rootfs != "" {
+ options = append(options, libpod.WithRootFS(s.Rootfs))
+ }
+ // Default used if not overridden on command line
+
+ if s.RestartPolicy != "" {
+ if s.RestartPolicy == "unless-stopped" {
+ return nil, errors.Wrapf(define.ErrInvalidArg, "the unless-stopped restart policy is not supported")
+ }
+ if s.RestartRetries != nil {
+ options = append(options, libpod.WithRestartRetries(*s.RestartRetries))
+ }
+ options = append(options, libpod.WithRestartPolicy(s.RestartPolicy))
+ }
+
+ if s.ContainerHealthCheckConfig.HealthConfig != nil {
+ options = append(options, libpod.WithHealthCheck(s.ContainerHealthCheckConfig.HealthConfig))
+ logrus.Debugf("New container has a health check")
+ }
+ return options, nil
+}
+
+func (s *SpecGenerator) createExitCommandOption(config *config.Config, podmanPath string) libpod.CtrCreateOption {
+ // We need a cleanup process for containers in the current model.
+ // But we can't assume that the caller is Podman - it could be another
+ // user of the API.
+ // As such, provide a way to specify a path to Podman, so we can
+ // still invoke a cleanup process.
+
+ command := []string{podmanPath,
+ "--root", config.StorageConfig.GraphRoot,
+ "--runroot", config.StorageConfig.RunRoot,
+ "--log-level", logrus.GetLevel().String(),
+ "--cgroup-manager", config.CgroupManager,
+ "--tmpdir", config.TmpDir,
+ }
+ if config.OCIRuntime != "" {
+ command = append(command, []string{"--runtime", config.OCIRuntime}...)
+ }
+ if config.StorageConfig.GraphDriverName != "" {
+ command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...)
+ }
+ for _, opt := range config.StorageConfig.GraphDriverOptions {
+ command = append(command, []string{"--storage-opt", opt}...)
+ }
+ if config.EventsLogger != "" {
+ command = append(command, []string{"--events-backend", config.EventsLogger}...)
+ }
+
+ // TODO Mheon wants to leave this for now
+ //if s.sys {
+ // command = append(command, "--syslog", "true")
+ //}
+ command = append(command, []string{"container", "cleanup"}...)
+
+ if s.Remove {
+ command = append(command, "--rm")
+ }
+ return libpod.WithExitCommand(command)
+}
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
new file mode 100644
index 000000000..17b180cde
--- /dev/null
+++ b/pkg/specgen/namespaces.go
@@ -0,0 +1,467 @@
+package specgen
+
+import (
+ "os"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/capabilities"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+type NamespaceMode string
+
+const (
+ // Host means the the namespace is derived from
+ // the host
+ Host NamespaceMode = "host"
+ // Path is the path to a namespace
+ Path NamespaceMode = "path"
+ // FromContainer means namespace is derived from a
+ // different container
+ FromContainer NamespaceMode = "container"
+ // FromPod indicates the namespace is derived from a pod
+ FromPod NamespaceMode = "pod"
+ // Private indicates the namespace is private
+ Private NamespaceMode = "private"
+ // NoNetwork indicates no network namespace should
+ // be joined. loopback should still exists
+ NoNetwork NamespaceMode = "none"
+ // Bridge indicates that a CNI network stack
+ // should be used
+ Bridge NamespaceMode = "bridge"
+ // Slirp indicates that a slirp4ns network stack should
+ // be used
+ Slirp NamespaceMode = "slirp4ns"
+)
+
+// Namespace describes the namespace
+type Namespace struct {
+ NSMode NamespaceMode `json:"nsmode,omitempty"`
+ Value string `json:"string,omitempty"`
+}
+
+// IsHost returns a bool if the namespace is host based
+func (n *Namespace) IsHost() bool {
+ return n.NSMode == Host
+}
+
+// IsPath indicates via bool if the namespace is based on a path
+func (n *Namespace) IsPath() bool {
+ return n.NSMode == Path
+}
+
+// IsContainer indicates via bool if the namespace is based on a container
+func (n *Namespace) IsContainer() bool {
+ return n.NSMode == FromContainer
+}
+
+// IsPod indicates via bool if the namespace is based on a pod
+func (n *Namespace) IsPod() bool {
+ return n.NSMode == FromPod
+}
+
+// IsPrivate indicates the namespace is private
+func (n *Namespace) IsPrivate() bool {
+ return n.NSMode == Private
+}
+
+// validate perform simple validation on the namespace to make sure it is not
+// invalid from the get-go
+func (n *Namespace) validate() error {
+ if n == nil {
+ return nil
+ }
+ switch n.NSMode {
+ case Host, Path, FromContainer, FromPod, Private, NoNetwork, Bridge, Slirp:
+ break
+ default:
+ return errors.Errorf("invalid network %q", n.NSMode)
+ }
+ // Path and From Container MUST have a string value set
+ if n.NSMode == Path || n.NSMode == FromContainer {
+ if len(n.Value) < 1 {
+ return errors.Errorf("namespace mode %s requires a value", n.NSMode)
+ }
+ } else {
+ // All others must NOT set a string value
+ if len(n.Value) > 0 {
+ return errors.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode)
+ }
+ }
+ return nil
+}
+
+func (s *SpecGenerator) generateNamespaceContainerOpts(rt *libpod.Runtime) ([]libpod.CtrCreateOption, error) {
+ var portBindings []ocicni.PortMapping
+ options := make([]libpod.CtrCreateOption, 0)
+
+ // Cgroups
+ switch {
+ case s.CgroupNS.IsPrivate():
+ ns := s.CgroupNS.Value
+ if _, err := os.Stat(ns); err != nil {
+ return nil, err
+ }
+ case s.CgroupNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.CgroupNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.CgroupNS.Value)
+ }
+ options = append(options, libpod.WithCgroupNSFrom(connectedCtr))
+ // TODO
+ //default:
+ // return nil, errors.New("cgroup name only supports private and container")
+ }
+
+ if s.CgroupParent != "" {
+ options = append(options, libpod.WithCgroupParent(s.CgroupParent))
+ }
+
+ if s.CgroupsMode != "" {
+ options = append(options, libpod.WithCgroupsMode(s.CgroupsMode))
+ }
+
+ // ipc
+ switch {
+ case s.IpcNS.IsHost():
+ options = append(options, libpod.WithShmDir("/dev/shm"))
+ case s.IpcNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.IpcNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.IpcNS.Value)
+ }
+ options = append(options, libpod.WithIPCNSFrom(connectedCtr))
+ options = append(options, libpod.WithShmDir(connectedCtr.ShmDir()))
+ }
+
+ // pid
+ if s.PidNS.IsContainer() {
+ connectedCtr, err := rt.LookupContainer(s.PidNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.PidNS.Value)
+ }
+ options = append(options, libpod.WithPIDNSFrom(connectedCtr))
+ }
+
+ // uts
+ switch {
+ case s.UtsNS.IsPod():
+ connectedPod, err := rt.LookupPod(s.UtsNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "pod %q not found", s.UtsNS.Value)
+ }
+ options = append(options, libpod.WithUTSNSFromPod(connectedPod))
+ case s.UtsNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.UtsNS.Value)
+ }
+
+ options = append(options, libpod.WithUTSNSFrom(connectedCtr))
+ }
+
+ if s.UseImageHosts {
+ options = append(options, libpod.WithUseImageHosts())
+ } else if len(s.HostAdd) > 0 {
+ options = append(options, libpod.WithHosts(s.HostAdd))
+ }
+
+ // User
+
+ switch {
+ case s.UserNS.IsPath():
+ ns := s.UserNS.Value
+ if ns == "" {
+ return nil, errors.Errorf("invalid empty user-defined user namespace")
+ }
+ _, err := os.Stat(ns)
+ if err != nil {
+ return nil, err
+ }
+ if s.IDMappings != nil {
+ options = append(options, libpod.WithIDMappings(*s.IDMappings))
+ }
+ case s.UserNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.UserNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.UserNS.Value)
+ }
+ options = append(options, libpod.WithUserNSFrom(connectedCtr))
+ default:
+ if s.IDMappings != nil {
+ options = append(options, libpod.WithIDMappings(*s.IDMappings))
+ }
+ }
+
+ options = append(options, libpod.WithUser(s.User))
+ options = append(options, libpod.WithGroups(s.Groups))
+
+ if len(s.PortMappings) > 0 {
+ portBindings = s.PortMappings
+ }
+
+ switch {
+ case s.NetNS.IsPath():
+ ns := s.NetNS.Value
+ if ns == "" {
+ return nil, errors.Errorf("invalid empty user-defined network namespace")
+ }
+ _, err := os.Stat(ns)
+ if err != nil {
+ return nil, err
+ }
+ case s.NetNS.IsContainer():
+ connectedCtr, err := rt.LookupContainer(s.NetNS.Value)
+ if err != nil {
+ return nil, errors.Wrapf(err, "container %q not found", s.NetNS.Value)
+ }
+ options = append(options, libpod.WithNetNSFrom(connectedCtr))
+ case !s.NetNS.IsHost() && s.NetNS.NSMode != NoNetwork:
+ postConfigureNetNS := !s.UserNS.IsHost()
+ options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(s.NetNS.NSMode), s.CNINetworks))
+ }
+
+ if len(s.DNSSearch) > 0 {
+ options = append(options, libpod.WithDNSSearch(s.DNSSearch))
+ }
+ if len(s.DNSServer) > 0 {
+ // TODO I'm not sure how we are going to handle this given the input
+ if len(s.DNSServer) == 1 { //&& strings.ToLower(s.DNSServer[0].) == "none" {
+ options = append(options, libpod.WithUseImageResolvConf())
+ } else {
+ var dnsServers []string
+ for _, d := range s.DNSServer {
+ dnsServers = append(dnsServers, d.String())
+ }
+ options = append(options, libpod.WithDNS(dnsServers))
+ }
+ }
+ if len(s.DNSOption) > 0 {
+ options = append(options, libpod.WithDNSOption(s.DNSOption))
+ }
+ if s.StaticIP != nil {
+ options = append(options, libpod.WithStaticIP(*s.StaticIP))
+ }
+
+ if s.StaticMAC != nil {
+ options = append(options, libpod.WithStaticMAC(*s.StaticMAC))
+ }
+ return options, nil
+}
+
+func (s *SpecGenerator) pidConfigureGenerator(g *generate.Generator) error {
+ if s.PidNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), s.PidNS.Value)
+ }
+ if s.PidNS.IsHost() {
+ return g.RemoveLinuxNamespace(string(spec.PIDNamespace))
+ }
+ if s.PidNS.IsContainer() {
+ logrus.Debugf("using container %s pidmode", s.PidNS.Value)
+ }
+ if s.PidNS.IsPod() {
+ logrus.Debug("using pod pidmode")
+ }
+ return nil
+}
+
+func (s *SpecGenerator) utsConfigureGenerator(g *generate.Generator, runtime *libpod.Runtime) error {
+ hostname := s.Hostname
+ var err error
+ if hostname == "" {
+ switch {
+ case s.UtsNS.IsContainer():
+ utsCtr, err := runtime.LookupContainer(s.UtsNS.Value)
+ if err != nil {
+ return errors.Wrapf(err, "unable to retrieve hostname from dependency container %s", s.UtsNS.Value)
+ }
+ hostname = utsCtr.Hostname()
+ case s.NetNS.IsHost() || s.UtsNS.IsHost():
+ hostname, err = os.Hostname()
+ if err != nil {
+ return errors.Wrap(err, "unable to retrieve hostname of the host")
+ }
+ default:
+ logrus.Debug("No hostname set; container's hostname will default to runtime default")
+ }
+ }
+ g.RemoveHostname()
+ if s.Hostname != "" || !s.UtsNS.IsHost() {
+ // Set the hostname in the OCI configuration only
+ // if specified by the user or if we are creating
+ // a new UTS namespace.
+ g.SetHostname(hostname)
+ }
+ g.AddProcessEnv("HOSTNAME", hostname)
+
+ if s.UtsNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), s.UtsNS.Value)
+ }
+ if s.UtsNS.IsHost() {
+ return g.RemoveLinuxNamespace(string(spec.UTSNamespace))
+ }
+ if s.UtsNS.IsContainer() {
+ logrus.Debugf("using container %s utsmode", s.UtsNS.Value)
+ }
+ return nil
+}
+
+func (s *SpecGenerator) ipcConfigureGenerator(g *generate.Generator) error {
+ if s.IpcNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), s.IpcNS.Value)
+ }
+ if s.IpcNS.IsHost() {
+ return g.RemoveLinuxNamespace(s.IpcNS.Value)
+ }
+ if s.IpcNS.IsContainer() {
+ logrus.Debugf("Using container %s ipcmode", s.IpcNS.Value)
+ }
+ return nil
+}
+
+func (s *SpecGenerator) cgroupConfigureGenerator(g *generate.Generator) error {
+ if s.CgroupNS.IsPath() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), s.CgroupNS.Value)
+ }
+ if s.CgroupNS.IsHost() {
+ return g.RemoveLinuxNamespace(s.CgroupNS.Value)
+ }
+ if s.CgroupNS.IsPrivate() {
+ return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), "")
+ }
+ if s.CgroupNS.IsContainer() {
+ logrus.Debugf("Using container %s cgroup mode", s.CgroupNS.Value)
+ }
+ return nil
+}
+
+func (s *SpecGenerator) networkConfigureGenerator(g *generate.Generator) error {
+ switch {
+ case s.NetNS.IsHost():
+ logrus.Debug("Using host netmode")
+ if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil {
+ return err
+ }
+
+ case s.NetNS.NSMode == NoNetwork:
+ logrus.Debug("Using none netmode")
+ case s.NetNS.NSMode == Bridge:
+ logrus.Debug("Using bridge netmode")
+ case s.NetNS.IsContainer():
+ logrus.Debugf("using container %s netmode", s.NetNS.Value)
+ case s.NetNS.IsPath():
+ logrus.Debug("Using ns netmode")
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), s.NetNS.Value); err != nil {
+ return err
+ }
+ case s.NetNS.IsPod():
+ logrus.Debug("Using pod netmode, unless pod is not sharing")
+ case s.NetNS.NSMode == Slirp:
+ logrus.Debug("Using slirp4netns netmode")
+ default:
+ return errors.Errorf("unknown network mode")
+ }
+
+ if g.Config.Annotations == nil {
+ g.Config.Annotations = make(map[string]string)
+ }
+
+ if s.PublishImagePorts {
+ g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseTrue
+ } else {
+ g.Config.Annotations[libpod.InspectAnnotationPublishAll] = libpod.InspectResponseFalse
+ }
+
+ return nil
+}
+
+func (s *SpecGenerator) userConfigureGenerator(g *generate.Generator) error {
+ if s.UserNS.IsPath() {
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), s.UserNS.Value); err != nil {
+ return err
+ }
+ // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping
+ g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1))
+ g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1))
+ }
+
+ if s.IDMappings != nil {
+ if (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) && !s.UserNS.IsHost() {
+ if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), ""); err != nil {
+ return err
+ }
+ }
+ for _, uidmap := range s.IDMappings.UIDMap {
+ g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size))
+ }
+ for _, gidmap := range s.IDMappings.GIDMap {
+ g.AddLinuxGIDMapping(uint32(gidmap.HostID), uint32(gidmap.ContainerID), uint32(gidmap.Size))
+ }
+ }
+ return nil
+}
+
+func (s *SpecGenerator) securityConfigureGenerator(g *generate.Generator, newImage *image.Image) error {
+ // HANDLE CAPABILITIES
+ // NOTE: Must happen before SECCOMP
+ if s.Privileged {
+ g.SetupPrivileged(true)
+ }
+
+ useNotRoot := func(user string) bool {
+ if user == "" || user == "root" || user == "0" {
+ return false
+ }
+ return true
+ }
+ configSpec := g.Config
+ var err error
+ var caplist []string
+ bounding := configSpec.Process.Capabilities.Bounding
+ if useNotRoot(s.User) {
+ configSpec.Process.Capabilities.Bounding = caplist
+ }
+ caplist, err = capabilities.MergeCapabilities(configSpec.Process.Capabilities.Bounding, s.CapAdd, s.CapDrop)
+ if err != nil {
+ return err
+ }
+
+ configSpec.Process.Capabilities.Bounding = caplist
+ configSpec.Process.Capabilities.Permitted = caplist
+ configSpec.Process.Capabilities.Inheritable = caplist
+ configSpec.Process.Capabilities.Effective = caplist
+ configSpec.Process.Capabilities.Ambient = caplist
+ if useNotRoot(s.User) {
+ caplist, err = capabilities.MergeCapabilities(bounding, s.CapAdd, s.CapDrop)
+ if err != nil {
+ return err
+ }
+ }
+ configSpec.Process.Capabilities.Bounding = caplist
+
+ // HANDLE SECCOMP
+ if s.SeccompProfilePath != "unconfined" {
+ seccompConfig, err := s.getSeccompConfig(configSpec, newImage)
+ if err != nil {
+ return err
+ }
+ configSpec.Linux.Seccomp = seccompConfig
+ }
+
+ // Clear default Seccomp profile from Generator for privileged containers
+ if s.SeccompProfilePath == "unconfined" || s.Privileged {
+ configSpec.Linux.Seccomp = nil
+ }
+
+ g.SetRootReadonly(s.ReadOnlyFilesystem)
+ for sysctlKey, sysctlVal := range s.Sysctl {
+ g.AddLinuxSysctl(sysctlKey, sysctlVal)
+ }
+
+ return nil
+}
diff --git a/pkg/specgen/oci.go b/pkg/specgen/oci.go
new file mode 100644
index 000000000..2523f21b3
--- /dev/null
+++ b/pkg/specgen/oci.go
@@ -0,0 +1,260 @@
+package specgen
+
+import (
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/rootless"
+ createconfig "github.com/containers/libpod/pkg/spec"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+func (s *SpecGenerator) toOCISpec(rt *libpod.Runtime, newImage *image.Image) (*spec.Spec, error) {
+ var (
+ inUserNS bool
+ )
+ cgroupPerm := "ro"
+ g, err := generate.New("linux")
+ if err != nil {
+ return nil, err
+ }
+ // Remove the default /dev/shm mount to ensure we overwrite it
+ g.RemoveMount("/dev/shm")
+ g.HostSpecific = true
+ addCgroup := true
+ canMountSys := true
+
+ isRootless := rootless.IsRootless()
+ if isRootless {
+ inUserNS = true
+ }
+ if !s.UserNS.IsHost() {
+ if s.UserNS.IsContainer() || s.UserNS.IsPath() {
+ inUserNS = true
+ }
+ if s.UserNS.IsPrivate() {
+ inUserNS = true
+ }
+ }
+ if inUserNS && s.NetNS.IsHost() {
+ canMountSys = false
+ }
+
+ if s.Privileged && canMountSys {
+ cgroupPerm = "rw"
+ g.RemoveMount("/sys")
+ sysMnt := spec.Mount{
+ Destination: "/sys",
+ Type: "sysfs",
+ Source: "sysfs",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", "rw"},
+ }
+ g.AddMount(sysMnt)
+ } else if !canMountSys {
+ addCgroup = false
+ g.RemoveMount("/sys")
+ r := "ro"
+ if s.Privileged {
+ r = "rw"
+ }
+ sysMnt := spec.Mount{
+ Destination: "/sys",
+ Type: "bind", // should we use a constant for this, like createconfig?
+ Source: "/sys",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"},
+ }
+ g.AddMount(sysMnt)
+ if !s.Privileged && isRootless {
+ g.AddLinuxMaskedPaths("/sys/kernel")
+ }
+ }
+ gid5Available := true
+ if isRootless {
+ nGids, err := createconfig.GetAvailableGids()
+ if err != nil {
+ return nil, err
+ }
+ gid5Available = nGids >= 5
+ }
+ // When using a different user namespace, check that the GID 5 is mapped inside
+ // the container.
+ if gid5Available && (s.IDMappings != nil && len(s.IDMappings.GIDMap) > 0) {
+ mappingFound := false
+ for _, r := range s.IDMappings.GIDMap {
+ if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size {
+ mappingFound = true
+ break
+ }
+ }
+ if !mappingFound {
+ gid5Available = false
+ }
+
+ }
+ if !gid5Available {
+ // If we have no GID mappings, the gid=5 default option would fail, so drop it.
+ g.RemoveMount("/dev/pts")
+ devPts := spec.Mount{
+ Destination: "/dev/pts",
+ Type: "devpts",
+ Source: "devpts",
+ Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"},
+ }
+ g.AddMount(devPts)
+ }
+
+ if inUserNS && s.IpcNS.IsHost() {
+ g.RemoveMount("/dev/mqueue")
+ devMqueue := spec.Mount{
+ Destination: "/dev/mqueue",
+ Type: "bind", // constant ?
+ Source: "/dev/mqueue",
+ Options: []string{"bind", "nosuid", "noexec", "nodev"},
+ }
+ g.AddMount(devMqueue)
+ }
+ if inUserNS && s.PidNS.IsHost() {
+ g.RemoveMount("/proc")
+ procMount := spec.Mount{
+ Destination: "/proc",
+ Type: createconfig.TypeBind,
+ Source: "/proc",
+ Options: []string{"rbind", "nosuid", "noexec", "nodev"},
+ }
+ g.AddMount(procMount)
+ }
+
+ if addCgroup {
+ cgroupMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup",
+ Type: "cgroup",
+ Source: "cgroup",
+ Options: []string{"rprivate", "nosuid", "noexec", "nodev", "relatime", cgroupPerm},
+ }
+ g.AddMount(cgroupMnt)
+ }
+ g.SetProcessCwd(s.WorkDir)
+ g.SetProcessArgs(s.Command)
+ g.SetProcessTerminal(s.Terminal)
+
+ for key, val := range s.Annotations {
+ g.AddAnnotation(key, val)
+ }
+ g.AddProcessEnv("container", "podman")
+
+ g.Config.Linux.Resources = s.ResourceLimits
+
+ // Devices
+ if s.Privileged {
+ // If privileged, we need to add all the host devices to the
+ // spec. We do not add the user provided ones because we are
+ // already adding them all.
+ if err := createconfig.AddPrivilegedDevices(&g); err != nil {
+ return nil, err
+ }
+ } else {
+ for _, device := range s.Devices {
+ if err := createconfig.DevicesFromPath(&g, device.Path); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ // SECURITY OPTS
+ g.SetProcessNoNewPrivileges(s.NoNewPrivileges)
+
+ if !s.Privileged {
+ g.SetProcessApparmorProfile(s.ApparmorProfile)
+ }
+
+ createconfig.BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), &g)
+
+ for name, val := range s.Env {
+ g.AddProcessEnv(name, val)
+ }
+
+ // TODO rlimits and ulimits needs further refinement by someone more
+ // familiar with the code.
+ //if err := addRlimits(config, &g); err != nil {
+ // return nil, err
+ //}
+
+ // NAMESPACES
+
+ if err := s.pidConfigureGenerator(&g); err != nil {
+ return nil, err
+ }
+
+ if err := s.userConfigureGenerator(&g); err != nil {
+ return nil, err
+ }
+
+ if err := s.networkConfigureGenerator(&g); err != nil {
+ return nil, err
+ }
+
+ if err := s.utsConfigureGenerator(&g, rt); err != nil {
+ return nil, err
+ }
+
+ if err := s.ipcConfigureGenerator(&g); err != nil {
+ return nil, err
+ }
+
+ if err := s.cgroupConfigureGenerator(&g); err != nil {
+ return nil, err
+ }
+ configSpec := g.Config
+
+ if err := s.securityConfigureGenerator(&g, newImage); err != nil {
+ return nil, err
+ }
+
+ // BIND MOUNTS
+ configSpec.Mounts = createconfig.SupercedeUserMounts(s.Mounts, configSpec.Mounts)
+ // Process mounts to ensure correct options
+ finalMounts, err := createconfig.InitFSMounts(configSpec.Mounts)
+ if err != nil {
+ return nil, err
+ }
+ configSpec.Mounts = finalMounts
+
+ // Add annotations
+ if configSpec.Annotations == nil {
+ configSpec.Annotations = make(map[string]string)
+ }
+
+ // TODO cidfile is not in specgen; when wiring up cli, we will need to move this out of here
+ // leaving as a reminder
+ //if config.CidFile != "" {
+ // configSpec.Annotations[libpod.InspectAnnotationCIDFile] = config.CidFile
+ //}
+
+ if s.Remove {
+ configSpec.Annotations[libpod.InspectAnnotationAutoremove] = libpod.InspectResponseTrue
+ } else {
+ configSpec.Annotations[libpod.InspectAnnotationAutoremove] = libpod.InspectResponseFalse
+ }
+
+ if len(s.VolumesFrom) > 0 {
+ configSpec.Annotations[libpod.InspectAnnotationVolumesFrom] = strings.Join(s.VolumesFrom, ",")
+ }
+
+ if s.Privileged {
+ configSpec.Annotations[libpod.InspectAnnotationPrivileged] = libpod.InspectResponseTrue
+ } else {
+ configSpec.Annotations[libpod.InspectAnnotationPrivileged] = libpod.InspectResponseFalse
+ }
+
+ // TODO Init might not make it into the specgen and therefore is not available here. We should deal
+ // with this when we wire up the CLI; leaving as a reminder
+ //if s.Init {
+ // configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseTrue
+ //} else {
+ // configSpec.Annotations[libpod.InspectAnnotationInit] = libpod.InspectResponseFalse
+ //}
+
+ return configSpec, nil
+}
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index e22ee598f..e1dfe4dc5 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -2,24 +2,28 @@ package specgen
import (
"net"
+ "syscall"
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
)
-// TODO
-// mheon provided this an off the cuff suggestion. Adding it here to retain
-// for history as we implement it. When this struct is implemented, we need
-// to remove the nolints.
-type Namespace struct {
- isHost bool //nolint
- isPath string //nolint
- isContainer string //nolint
- isPod bool //nolint
+// LogConfig describes the logging characteristics for a container
+type LogConfig struct {
+ // LogDriver is the container's log driver.
+ // Optional.
+ Driver string `json:"driver,omitempty"`
+ // LogPath is the path the container's logs will be stored at.
+ // Only available if LogDriver is set to "json-file" or "k8s-file".
+ // Optional.
+ Path string `json:"path,omitempty"`
+ // A set of options to accompany the log driver.
+ // Optional.
+ Options map[string]string `json:"options,omitempty"`
}
// ContainerBasicConfig contains the basic parts of a container.
@@ -62,7 +66,7 @@ type ContainerBasicConfig struct {
// If not provided, the default, SIGTERM, will be used.
// Will conflict with Systemd if Systemd is set to "true" or "always".
// Optional.
- StopSignal *uint `json:"stop_signal,omitempty"`
+ StopSignal *syscall.Signal `json:"stop_signal,omitempty"`
// StopTimeout is a timeout between the container's stop signal being
// sent and SIGKILL being sent.
// If not provided, the default will be used.
@@ -70,13 +74,10 @@ type ContainerBasicConfig struct {
// instead.
// Optional.
StopTimeout *uint `json:"stop_timeout,omitempty"`
- // LogDriver is the container's log driver.
- // Optional.
- LogDriver string `json:"log_driver,omitempty"`
- // LogPath is the path the container's logs will be stored at.
- // Only available if LogDriver is set to "json-file" or "k8s-file".
- // Optional.
- LogPath string `json:"log_path,omitempty"`
+ // LogConfiguration describes the logging for a container including
+ // driver, path, and options.
+ // Optional
+ LogConfiguration *LogConfig `json:"log_configuration,omitempty"`
// ConmonPidFile is a path at which a PID file for Conmon will be
// placed.
// If not given, a default location will be used.
@@ -111,12 +112,10 @@ type ContainerBasicConfig struct {
// Namespace is the libpod namespace the container will be placed in.
// Optional.
Namespace string `json:"namespace,omitempty"`
-
// PidNS is the container's PID namespace.
// It defaults to private.
// Mandatory.
PidNS Namespace `json:"pidns,omitempty"`
-
// UtsNS is the container's UTS namespace.
// It defaults to private.
// Must be set to Private to set Hostname.
@@ -128,6 +127,11 @@ type ContainerBasicConfig struct {
// Conflicts with UtsNS if UtsNS is not set to private.
// Optional.
Hostname string `json:"hostname,omitempty"`
+ // Sysctl sets kernel parameters for the container
+ Sysctl map[string]string `json:"sysctl,omitempty"`
+ // Remove indicates if the container should be removed once it has been started
+ // and exits
+ Remove bool `json:"remove"`
}
// ContainerStorageConfig contains information on the storage configuration of a
@@ -175,7 +179,7 @@ type ContainerStorageConfig struct {
// Mandatory.
IpcNS Namespace `json:"ipcns,omitempty"`
// ShmSize is the size of the tmpfs to mount in at /dev/shm, in bytes.
- // Conflicts with ShmSize if ShmSize is not private.
+ // Conflicts with ShmSize if IpcNS is not private.
// Optional.
ShmSize *int64 `json:"shm_size,omitempty"`
// WorkDir is the container's working directory.
@@ -234,6 +238,9 @@ type ContainerSecurityConfig struct {
// will use.
// Optional.
ApparmorProfile string `json:"apparmor_profile,omitempty"`
+ // SeccompPolicy determines which seccomp profile gets applied
+ // the container. valid values: empty,default,image
+ SeccompPolicy string `json:"seccomp_policy,omitempty"`
// SeccompProfilePath is the path to a JSON file containing the
// container's Seccomp profile.
// If not specified, no Seccomp profile will be used.
@@ -252,7 +259,10 @@ type ContainerSecurityConfig struct {
// IDMappings are UID and GID mappings that will be used by user
// namespaces.
// Required if UserNS is private.
- IDMappings storage.IDMappingOptions `json:"idmappings,omitempty"`
+ IDMappings *storage.IDMappingOptions `json:"idmappings,omitempty"`
+ // ReadOnlyFilesystem indicates that everything will be mounted
+ // as read-only
+ ReadOnlyFilesystem bool `json:"read_only_filesystem,omittempty"`
}
// ContainerCgroupConfig contains configuration information about a container's
@@ -260,16 +270,13 @@ type ContainerSecurityConfig struct {
type ContainerCgroupConfig struct {
// CgroupNS is the container's cgroup namespace.
// It defaults to private.
- // Conflicts with NoCgroups if not set to host.
// Mandatory.
CgroupNS Namespace `json:"cgroupns,omitempty"`
- // NoCgroups indicates that the container should not create CGroups.
- // Conflicts with CgroupParent and CgroupNS if CgroupNS is not set to
- // host.
- NoCgroups bool `json:"no_cgroups,omitempty"`
+ // CgroupsMode sets a policy for how cgroups will be created in the
+ // container, including the ability to disable creation entirely.
+ CgroupsMode string `json:"cgroups_mode,omitempty"`
// CgroupParent is the container's CGroup parent.
// If not set, the default for the current cgroup driver will be used.
- // Conflicts with NoCgroups.
// Optional.
CgroupParent string `json:"cgroup_parent,omitempty"`
}
@@ -348,7 +355,7 @@ type ContainerNetworkConfig struct {
// ContainerResourceConfig contains information on container resource limits.
type ContainerResourceConfig struct {
- // ResourceLimits are resource limits to apply to the container.
+ // ResourceLimits are resource limits to apply to the container.,
// Can only be set as root on cgroups v1 systems, but can be set as
// rootless as well for cgroups v2.
// Optional.
@@ -365,11 +372,12 @@ type ContainerResourceConfig struct {
// ContainerHealthCheckConfig describes a container healthcheck with attributes
// like command, retries, interval, start period, and timeout.
type ContainerHealthCheckConfig struct {
- HealthConfig manifest.Schema2HealthConfig `json:"healthconfig,omitempty"`
+ HealthConfig *manifest.Schema2HealthConfig `json:"healthconfig,omitempty"`
}
// SpecGenerator creates an OCI spec and Libpod configuration options to create
// a container based on the given configuration.
+// swagger:model SpecGenerator
type SpecGenerator struct {
ContainerBasicConfig
ContainerStorageConfig
@@ -381,19 +389,24 @@ type SpecGenerator struct {
}
// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
-func NewSpecGenerator(image, rootfs *string) (*SpecGenerator, error) {
- _ = image
- _ = rootfs
- return &SpecGenerator{}, define.ErrNotImplemented
-}
-
-// Validate verifies that the given SpecGenerator is valid and satisfies required
-// input for creating a container.
-func (s *SpecGenerator) Validate() error {
- return define.ErrNotImplemented
+func NewSpecGenerator(image string) *SpecGenerator {
+ net := ContainerNetworkConfig{
+ NetNS: Namespace{
+ NSMode: Bridge,
+ },
+ }
+ csc := ContainerStorageConfig{Image: image}
+ if rootless.IsRootless() {
+ net.NetNS.NSMode = Slirp
+ }
+ return &SpecGenerator{
+ ContainerStorageConfig: csc,
+ ContainerNetworkConfig: net,
+ }
}
-// MakeContainer creates a container based on the SpecGenerator
-func (s *SpecGenerator) MakeContainer() (*libpod.Container, error) {
- return nil, define.ErrNotImplemented
+// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
+func NewSpecGeneratorWithRootfs(rootfs string) *SpecGenerator {
+ csc := ContainerStorageConfig{Rootfs: rootfs}
+ return &SpecGenerator{ContainerStorageConfig: csc}
}
diff --git a/pkg/specgen/validate.go b/pkg/specgen/validate.go
new file mode 100644
index 000000000..78e4d8ad5
--- /dev/null
+++ b/pkg/specgen/validate.go
@@ -0,0 +1,159 @@
+package specgen
+
+import (
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+)
+
+var (
+ // ErrInvalidSpecConfig describes an error that the given SpecGenerator is invalid
+ ErrInvalidSpecConfig error = errors.New("invalid configuration")
+ // SystemDValues describes the only values that SystemD can be
+ SystemDValues = []string{"true", "false", "always"}
+ // ImageVolumeModeValues describes the only values that ImageVolumeMode can be
+ ImageVolumeModeValues = []string{"ignore", "tmpfs", "anonymous"}
+)
+
+func exclusiveOptions(opt1, opt2 string) error {
+ return errors.Errorf("%s and %s are mutually exclusive options", opt1, opt2)
+}
+
+// Validate verifies that the given SpecGenerator is valid and satisfies required
+// input for creating a container.
+func (s *SpecGenerator) validate(rt *libpod.Runtime) error {
+
+ //
+ // ContainerBasicConfig
+ //
+ // Rootfs and Image cannot both populated
+ if len(s.ContainerStorageConfig.Image) > 0 && len(s.ContainerStorageConfig.Rootfs) > 0 {
+ return errors.Wrap(ErrInvalidSpecConfig, "both image and rootfs cannot be simultaneously")
+ }
+ // Cannot set hostname and utsns
+ if len(s.ContainerBasicConfig.Hostname) > 0 && !s.ContainerBasicConfig.UtsNS.IsPrivate() {
+ return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when creating an UTS namespace")
+ }
+ // systemd values must be true, false, or always
+ if len(s.ContainerBasicConfig.Systemd) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerBasicConfig.Systemd), SystemDValues) {
+ return errors.Wrapf(ErrInvalidSpecConfig, "SystemD values must be one of %s", strings.Join(SystemDValues, ","))
+ }
+
+ //
+ // ContainerStorageConfig
+ //
+ // rootfs and image cannot both be set
+ if len(s.ContainerStorageConfig.Image) > 0 && len(s.ContainerStorageConfig.Rootfs) > 0 {
+ return exclusiveOptions("rootfs", "image")
+ }
+ // imagevolumemode must be one of ignore, tmpfs, or anonymous if given
+ if len(s.ContainerStorageConfig.ImageVolumeMode) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerStorageConfig.ImageVolumeMode), ImageVolumeModeValues) {
+ return errors.Errorf("ImageVolumeMode values must be one of %s", strings.Join(ImageVolumeModeValues, ","))
+ }
+ // shmsize conflicts with IPC namespace
+ if s.ContainerStorageConfig.ShmSize != nil && !s.ContainerStorageConfig.IpcNS.IsPrivate() {
+ return errors.New("cannot set shmsize when creating an IPC namespace")
+ }
+
+ //
+ // ContainerSecurityConfig
+ //
+ // groups and privileged are exclusive
+ if len(s.Groups) > 0 && s.Privileged {
+ return exclusiveOptions("Groups", "privileged")
+ }
+ // capadd and privileged are exclusive
+ if len(s.CapAdd) > 0 && s.Privileged {
+ return exclusiveOptions("CapAdd", "privileged")
+ }
+ // selinuxprocesslabel and privileged are exclusive
+ if len(s.SelinuxProcessLabel) > 0 && s.Privileged {
+ return exclusiveOptions("SelinuxProcessLabel", "privileged")
+ }
+ // selinuxmounmtlabel and privileged are exclusive
+ if len(s.SelinuxMountLabel) > 0 && s.Privileged {
+ return exclusiveOptions("SelinuxMountLabel", "privileged")
+ }
+ // selinuxopts and privileged are exclusive
+ if len(s.SelinuxOpts) > 0 && s.Privileged {
+ return exclusiveOptions("SelinuxOpts", "privileged")
+ }
+ // apparmor and privileged are exclusive
+ if len(s.ApparmorProfile) > 0 && s.Privileged {
+ return exclusiveOptions("AppArmorProfile", "privileged")
+ }
+ // userns and idmappings conflict
+ if s.UserNS.IsPrivate() && s.IDMappings == nil {
+ return errors.Wrap(ErrInvalidSpecConfig, "IDMappings are required when not creating a User namespace")
+ }
+
+ //
+ // ContainerCgroupConfig
+ //
+ //
+ // None for now
+
+ //
+ // ContainerNetworkConfig
+ //
+ if !s.NetNS.IsPrivate() && s.ConfigureNetNS {
+ return errors.New("can only configure network namespace when creating a network a network namespace")
+ }
+ // useimageresolveconf conflicts with dnsserver, dnssearch, dnsoption
+ if s.UseImageResolvConf {
+ if len(s.DNSServer) > 0 {
+ return exclusiveOptions("UseImageResolvConf", "DNSServer")
+ }
+ if len(s.DNSSearch) > 0 {
+ return exclusiveOptions("UseImageResolvConf", "DNSSearch")
+ }
+ if len(s.DNSOption) > 0 {
+ return exclusiveOptions("UseImageResolvConf", "DNSOption")
+ }
+ }
+ // UseImageHosts and HostAdd are exclusive
+ if s.UseImageHosts && len(s.HostAdd) > 0 {
+ return exclusiveOptions("UseImageHosts", "HostAdd")
+ }
+
+ // TODO the specgen does not appear to handle this? Should it
+ //switch config.Cgroup.Cgroups {
+ //case "disabled":
+ // if addedResources {
+ // return errors.New("cannot specify resource limits when cgroups are disabled is specified")
+ // }
+ // configSpec.Linux.Resources = &spec.LinuxResources{}
+ //case "enabled", "no-conmon", "":
+ // // Do nothing
+ //default:
+ // return errors.New("unrecognized option for cgroups; supported are 'default', 'disabled', 'no-conmon'")
+ //}
+
+ // Namespaces
+ if err := s.UtsNS.validate(); err != nil {
+ return err
+ }
+ if err := s.IpcNS.validate(); err != nil {
+ return err
+ }
+ if err := s.NetNS.validate(); err != nil {
+ return err
+ }
+ if err := s.PidNS.validate(); err != nil {
+ return err
+ }
+ if err := s.CgroupNS.validate(); err != nil {
+ return err
+ }
+ if err := s.UserNS.validate(); err != nil {
+ return err
+ }
+
+ // The following are defaults as needed by container creation
+ if len(s.WorkDir) < 1 {
+ s.WorkDir = "/"
+ }
+ return nil
+}
diff --git a/pkg/systemd/activation.go b/pkg/systemd/activation.go
new file mode 100644
index 000000000..c8b2389dc
--- /dev/null
+++ b/pkg/systemd/activation.go
@@ -0,0 +1,40 @@
+package systemd
+
+import (
+ "os"
+ "strconv"
+ "strings"
+)
+
+// SocketActivated determine if podman is running under the socket activation protocol
+func SocketActivated() bool {
+ pid, pid_found := os.LookupEnv("LISTEN_PID")
+ fds, fds_found := os.LookupEnv("LISTEN_FDS")
+ fdnames, fdnames_found := os.LookupEnv("LISTEN_FDNAMES")
+
+ if !(pid_found && fds_found && fdnames_found) {
+ return false
+ }
+
+ p, err := strconv.Atoi(pid)
+ if err != nil || p != os.Getpid() {
+ return false
+ }
+
+ nfds, err := strconv.Atoi(fds)
+ if err != nil || nfds < 1 {
+ return false
+ }
+
+ // First available file descriptor is always 3.
+ if nfds > 1 {
+ names := strings.Split(fdnames, ":")
+ for _, n := range names {
+ if strings.Contains(n, "podman") {
+ return true
+ }
+ }
+ }
+
+ return true
+}
diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemd/generate/systemdgen.go
index 26b3b3756..404347828 100644
--- a/pkg/systemdgen/systemdgen.go
+++ b/pkg/systemd/generate/systemdgen.go
@@ -1,4 +1,4 @@
-package systemdgen
+package generate
import (
"bytes"
diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemd/generate/systemdgen_test.go
index ee2429407..b74b75258 100644
--- a/pkg/systemdgen/systemdgen_test.go
+++ b/pkg/systemd/generate/systemdgen_test.go
@@ -1,4 +1,4 @@
-package systemdgen
+package generate
import (
"testing"
diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go
index 0b78a8150..c6aed9943 100644
--- a/pkg/util/utils_supported.go
+++ b/pkg/util/utils_supported.go
@@ -33,7 +33,7 @@ func GetRuntimeDir() (string, error) {
logrus.Debugf("unable to make temp dir %s", tmpDir)
}
st, err := os.Stat(tmpDir)
- if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) {
runtimeDir = tmpDir
}
}
@@ -43,7 +43,7 @@ func GetRuntimeDir() (string, error) {
logrus.Debugf("unable to make temp dir %s", tmpDir)
}
st, err := os.Stat(tmpDir)
- if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && (st.Mode().Perm()&0700 == 0700) {
runtimeDir = tmpDir
}
}
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index 1ebe5d424..2ec45f7a1 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -16,6 +16,14 @@ import (
// CreatePod ...
func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCreate) error {
var options []libpod.PodCreateOption
+ if create.Infra {
+ options = append(options, libpod.WithInfraContainer())
+ nsOptions, err := shared.GetNamespaceOptions(create.Share)
+ if err != nil {
+ return err
+ }
+ options = append(options, nsOptions...)
+ }
if create.CgroupParent != "" {
options = append(options, libpod.WithPodCgroupParent(create.CgroupParent))
}
@@ -43,14 +51,6 @@ func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCrea
options = append(options, libpod.WithInfraContainerPorts(portBindings))
}
- if create.Infra {
- options = append(options, libpod.WithInfraContainer())
- nsOptions, err := shared.GetNamespaceOptions(create.Share)
- if err != nil {
- return err
- }
- options = append(options, nsOptions...)
- }
options = append(options, libpod.WithPodCgroups())
pod, err := i.Runtime.NewPod(getContext(), options...)
diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at
index a54063260..b8a049cdf 100644
--- a/test/apiv2/01-basic.at
+++ b/test/apiv2/01-basic.at
@@ -47,4 +47,19 @@ t GET info 200 \
.DefaultRuntime=runc \
.MemTotal~[0-9]\\+
+# Timing: make sure server stays responsive
+t0=$SECONDS
+for i in $(seq 1 10); do
+ # FIXME: someday: refactor t(), separate out the 'curl' logic so we
+ # can call it directly. Then we won't get ten annoying 'ok' lines.
+ t GET info 200
+done
+t1=$SECONDS
+delta_t=$((t1 - t2))
+if [ $delta_t -le 5 ]; then
+ _show_ok 1 "Time for ten /info requests ($delta_t seconds) <= 5s"
+else
+ _show_ok 0 "Time for ten /info requests" "<= 5 seconds" "$delta_t seconds"
+fi
+
# vim: filetype=sh
diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at
index 705de94d2..8b5651cff 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -3,18 +3,20 @@
# 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=$expected_id
+t POST libpod/pods/create name=foo 201 .id~[0-9a-f]\\{64\\}
+pod_id=$(jq -r .id <<<"$output")
t GET libpod/pods/foo/exists 204
+t GET libpod/pods/$pod_id/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
+t GET libpod/pods/foo/json 200 \
+ .Config.name=foo \
+ .Config.id=$pod_id \
+ .Containers=null
+t GET libpod/pods/json 200 \
+ .[0].Config.name=foo \
+ .[0].Config.id=$pod_id \
+ .[0].Containers=null
# Cannot create a dup pod with the same name
t POST libpod/pods/create name=foo 409 .cause="pod already exists"
@@ -35,8 +37,10 @@ t POST libpod/pods/foo/restart '' 500 .cause="no such container"
t POST libpod/pods/bar/restart '' 404
-#t POST libpod/pods/prune '' 200 # FIXME: unimplemented, returns 500
-#t POST libpod/pods/prune 'a=b' 400 # FIXME: unimplemented, returns 500
+# FIXME: I'm not sure what 'prune' is supposed to do; as of 20200224 it
+# just returns 200 (ok) with empty result list.
+#t POST libpod/pods/prune '' 200 # FIXME: 2020-02-24 returns 200 {}
+#t POST libpod/pods/prune 'a=b' 400 # FIXME: 2020-02-24 returns 200
# Clean up; and try twice, making sure that the second time fails
t DELETE libpod/pods/foo 204
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index fffd7b085..bc2ed142c 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -253,7 +253,7 @@ function start_service() {
die "Cannot start service on non-localhost ($HOST)"
fi
- $PODMAN_BIN --root $WORKDIR system service --timeout 15000 tcp:127.0.0.1:$PORT \
+ $PODMAN_BIN --root $WORKDIR system service --timeout 15 tcp:127.0.0.1:$PORT \
&> $WORKDIR/server.log &
service_pid=$!
diff --git a/test/e2e/create_staticip_test.go b/test/e2e/create_staticip_test.go
index 72a0638f9..693795637 100644
--- a/test/e2e/create_staticip_test.go
+++ b/test/e2e/create_staticip_test.go
@@ -4,6 +4,7 @@ package integration
import (
"os"
+ "time"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
@@ -86,8 +87,23 @@ var _ = Describe("Podman create with --ip flag", func() {
result = podmanTest.Podman([]string{"start", "test1"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
+
+ // race prevention: wait until IP address is assigned
+ for i := 0; i < 5; i++ {
+ result = podmanTest.Podman([]string{"inspect", "--format", "{{.NetworkSettings.IPAddress}}", "test1"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ if result.OutputToString() != "" {
+ break
+ }
+ time.Sleep(1 * time.Second)
+ }
+ Expect(result.OutputToString()).To(Equal(ip))
+
+ // test1 container is running with the given IP.
result = podmanTest.Podman([]string{"start", "test2"})
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
+ Expect(result.ErrorToString()).To(ContainSubstring("requested IP address " + ip + " is not available"))
})
})
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index 7633261e3..19a8658ac 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -41,6 +41,26 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(session).To(ExitWithError())
})
+ It("podman disable healthcheck with --no-healthcheck on valid container", func() {
+ SkipIfRemote()
+ session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"})
+ hc.WaitWithDefaultTimeout()
+ Expect(hc.ExitCode()).To(Equal(125))
+ })
+
+ It("podman disable healthcheck with --health-cmd=none on valid container", func() {
+ SkipIfRemote()
+ session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "none", "--name", "hc", healthcheck})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ hc := podmanTest.Podman([]string{"healthcheck", "run", "hc"})
+ hc.WaitWithDefaultTimeout()
+ Expect(hc.ExitCode()).To(Equal(125))
+ })
+
It("podman healthcheck on valid container", func() {
Skip("Extremely consistent flake - re-enable on debugging")
session := podmanTest.Podman([]string{"run", "-dt", "--name", "hc", healthcheck})
diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go
index 78c9b52d9..42698d270 100644
--- a/test/e2e/login_logout_test.go
+++ b/test/e2e/login_logout_test.go
@@ -19,14 +19,15 @@ import (
var _ = Describe("Podman login and logout", func() {
var (
- tempdir string
- err error
- podmanTest *PodmanTestIntegration
- authPath string
- certPath string
- port int
- server string
- testImg string
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ authPath string
+ certPath string
+ port int
+ server string
+ testImg string
+ registriesConfWithSearch []byte
)
BeforeEach(func() {
@@ -64,6 +65,9 @@ var _ = Describe("Podman login and logout", func() {
f.Sync()
port = 4999 + config.GinkgoConfig.ParallelNode
server = strings.Join([]string{"localhost", strconv.Itoa(port)}, ":")
+
+ registriesConfWithSearch = []byte(fmt.Sprintf("[registries.search]\nregistries = ['%s']", server))
+
testImg = strings.Join([]string{server, "test-apline"}, "/")
os.MkdirAll(filepath.Join("/etc/containers/certs.d", server), os.ModePerm)
@@ -113,6 +117,38 @@ var _ = Describe("Podman login and logout", func() {
Expect(session).To(ExitWithError())
})
+ It("podman login and logout without registry parameter", func() {
+ SkipIfRootless()
+
+ registriesConf, err := ioutil.TempFile("", "TestLoginWithoutParameter")
+ Expect(err).To(BeNil())
+ defer registriesConf.Close()
+ defer os.Remove(registriesConf.Name())
+
+ err = ioutil.WriteFile(registriesConf.Name(), []byte(registriesConfWithSearch), os.ModePerm)
+ Expect(err).To(BeNil())
+
+ // Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not
+ // run in parallel unless they opt in by calling t.Parallel(). So don’t do that.
+ oldRCP, hasRCP := os.LookupEnv("REGISTRIES_CONFIG_PATH")
+ defer func() {
+ if hasRCP {
+ os.Setenv("REGISTRIES_CONFIG_PATH", oldRCP)
+ } else {
+ os.Unsetenv("REGISTRIES_CONFIG_PATH")
+ }
+ }()
+ os.Setenv("REGISTRIES_CONFIG_PATH", registriesConf.Name())
+
+ session := podmanTest.Podman([]string{"login", "-u", "podmantest", "-p", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To((Equal(0)))
+
+ session = podmanTest.Podman([]string{"logout"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman login and logout with flag --authfile", func() {
SkipIfRootless()
authFile := filepath.Join(podmanTest.TempDir, "auth.json")
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 9aed5351a..440d307b5 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -4,13 +4,15 @@ package integration
import (
"fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
. "github.com/containers/libpod/test/utils"
"github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "io/ioutil"
- "os"
- "path/filepath"
)
func writeConf(conf []byte, confPath string) {
@@ -155,4 +157,76 @@ var _ = Describe("Podman network", func() {
Expect(session.IsJSONOutputValid()).To(BeTrue())
})
+ It("podman inspect container single CNI network", func() {
+ SkipIfRootless()
+ netName := "testNetSingleCNI"
+ network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName})
+ network.WaitWithDefaultTimeout()
+ Expect(network.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(netName)
+
+ ctrName := "testCtr"
+ container := podmanTest.Podman([]string{"run", "-dt", "--network", netName, "--name", ctrName, ALPINE, "top"})
+ container.WaitWithDefaultTimeout()
+ Expect(container.ExitCode()).To(BeZero())
+
+ inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(BeZero())
+ conData := inspect.InspectContainerToJSON()
+ Expect(len(conData)).To(Equal(1))
+ Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(1))
+ net, ok := conData[0].NetworkSettings.Networks[netName]
+ Expect(ok).To(BeTrue())
+ Expect(net.NetworkID).To(Equal(netName))
+ Expect(net.IPPrefixLen).To(Equal(24))
+ Expect(strings.HasPrefix(net.IPAddress, "10.50.50.")).To(BeTrue())
+
+ // Necessary to ensure the CNI network is removed cleanly
+ rmAll := podmanTest.Podman([]string{"rm", "-f", ctrName})
+ rmAll.WaitWithDefaultTimeout()
+ Expect(rmAll.ExitCode()).To(BeZero())
+ })
+
+ It("podman inspect container two CNI networks", func() {
+ SkipIfRootless()
+ netName1 := "testNetTwoCNI1"
+ network1 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.0/25", netName1})
+ network1.WaitWithDefaultTimeout()
+ Expect(network1.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(netName1)
+
+ netName2 := "testNetTwoCNI2"
+ network2 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.128/26", netName2})
+ network2.WaitWithDefaultTimeout()
+ Expect(network2.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(netName2)
+
+ ctrName := "testCtr"
+ container := podmanTest.Podman([]string{"run", "-dt", "--network", fmt.Sprintf("%s,%s", netName1, netName2), "--name", ctrName, ALPINE, "top"})
+ container.WaitWithDefaultTimeout()
+ Expect(container.ExitCode()).To(BeZero())
+
+ inspect := podmanTest.Podman([]string{"inspect", ctrName})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(BeZero())
+ conData := inspect.InspectContainerToJSON()
+ Expect(len(conData)).To(Equal(1))
+ Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(2))
+ net1, ok := conData[0].NetworkSettings.Networks[netName1]
+ Expect(ok).To(BeTrue())
+ Expect(net1.NetworkID).To(Equal(netName1))
+ Expect(net1.IPPrefixLen).To(Equal(25))
+ Expect(strings.HasPrefix(net1.IPAddress, "10.50.51.")).To(BeTrue())
+ net2, ok := conData[0].NetworkSettings.Networks[netName2]
+ Expect(ok).To(BeTrue())
+ Expect(net2.NetworkID).To(Equal(netName2))
+ Expect(net2.IPPrefixLen).To(Equal(26))
+ Expect(strings.HasPrefix(net2.IPAddress, "10.50.51.")).To(BeTrue())
+
+ // Necessary to ensure the CNI network is removed cleanly
+ rmAll := podmanTest.Podman([]string{"rm", "-f", ctrName})
+ rmAll.WaitWithDefaultTimeout()
+ Expect(rmAll.ExitCode()).To(BeZero())
+ })
})
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 2efa36141..e0a10c202 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -1,7 +1,9 @@
package integration
import (
+ "fmt"
"os"
+ "strings"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
@@ -117,4 +119,167 @@ var _ = Describe("Podman pod create", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
})
+
+ It("podman create pod with --no-hosts", func() {
+ SkipIfRemote()
+ name := "test"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--no-hosts", "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ alpineResolvConf := podmanTest.Podman([]string{"run", "-ti", "--rm", "--no-hosts", ALPINE, "cat", "/etc/hosts"})
+ alpineResolvConf.WaitWithDefaultTimeout()
+ Expect(alpineResolvConf.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "cat", "/etc/hosts"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(podResolvConf.OutputToString()).To(Equal(alpineResolvConf.OutputToString()))
+ })
+
+ It("podman create pod with --no-hosts and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--no-hosts", "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with --add-host", func() {
+ SkipIfRemote()
+ name := "test"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--add-host", "test.example.com:12.34.56.78", "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "cat", "/etc/hosts"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), "12.34.56.78 test.example.com")).To(BeTrue())
+ })
+
+ It("podman create pod with --add-host and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--add-host", "test.example.com:12.34.56.78", "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with DNS server set", func() {
+ SkipIfRemote()
+ name := "test"
+ server := "12.34.56.78"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns", server, "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "cat", "/etc/resolv.conf"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), fmt.Sprintf("nameserver %s", server))).To(BeTrue())
+ })
+
+ It("podman create pod with DNS server set and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ server := "12.34.56.78"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns", server, "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with DNS option set", func() {
+ SkipIfRemote()
+ name := "test"
+ option := "attempts:5"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns-opt", option, "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "cat", "/etc/resolv.conf"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), fmt.Sprintf("options %s", option))).To(BeTrue())
+ })
+
+ It("podman create pod with DNS option set and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ option := "attempts:5"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns-opt", option, "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with DNS search domain set", func() {
+ SkipIfRemote()
+ name := "test"
+ search := "example.com"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns-search", search, "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "cat", "/etc/resolv.conf"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), fmt.Sprintf("search %s", search))).To(BeTrue())
+ })
+
+ It("podman create pod with DNS search domain set and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ search := "example.com"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--dns-search", search, "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with IP address", func() {
+ SkipIfRemote()
+ SkipIfRootless()
+ name := "test"
+ ip := GetRandomIPAddress()
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), ip)).To(BeTrue())
+ })
+
+ It("podman create pod with IP address and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ ip := GetRandomIPAddress()
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
+
+ It("podman create pod with MAC address", func() {
+ SkipIfRemote()
+ SkipIfRootless()
+ name := "test"
+ mac := "92:d0:c6:0a:29:35"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--mac-address", mac, "--name", name})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
+ podResolvConf.WaitWithDefaultTimeout()
+ Expect(podResolvConf.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(podResolvConf.OutputToString(), mac)).To(BeTrue())
+ })
+
+ It("podman create pod with MAC address and no infra should fail", func() {
+ SkipIfRemote()
+ name := "test"
+ mac := "92:d0:c6:0a:29:35"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--mac-address", mac, "--name", name, "--infra=false"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(125))
+ })
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 48dd186e2..adbb9c16c 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -170,10 +170,11 @@ var _ = Describe("Podman ps", func() {
_, ec, _ := podmanTest.RunLsContainer("test1")
Expect(ec).To(Equal(0))
- result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.Labels}}"})
+ result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.ImageID}} {{.Labels}}"})
result.WaitWithDefaultTimeout()
Expect(strings.Contains(result.OutputToStringArray()[0], "table")).To(BeFalse())
Expect(strings.Contains(result.OutputToStringArray()[0], "ID")).To(BeTrue())
+ Expect(strings.Contains(result.OutputToStringArray()[0], "ImageID")).To(BeTrue())
Expect(strings.Contains(result.OutputToStringArray()[1], "alpine:latest")).To(BeTrue())
Expect(result.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go
index a45735a8a..d60f2a8cd 100644
--- a/test/e2e/run_memory_test.go
+++ b/test/e2e/run_memory_test.go
@@ -70,7 +70,11 @@ var _ = Describe("Podman run memory", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(Equal("41943040"))
+ if cgroupsv2 {
+ Expect(session.OutputToString()).To(Equal("max"))
+ } else {
+ Expect(session.OutputToString()).To(Equal("41943040"))
+ }
})
It("podman run memory-swappiness test", func() {
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 5e587b198..5be9db810 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -146,6 +146,17 @@ var _ = Describe("Podman run networking", func() {
Expect(match).Should(BeTrue())
})
+ It("podman run --net container: and --uts container:", func() {
+ ctrName := "ctrToJoin"
+ ctr1 := podmanTest.RunTopContainer(ctrName)
+ ctr1.WaitWithDefaultTimeout()
+ Expect(ctr1.ExitCode()).To(Equal(0))
+
+ ctr2 := podmanTest.Podman([]string{"run", "-d", "--net=container:" + ctrName, "--uts=container:" + ctrName, ALPINE, "true"})
+ ctr2.WaitWithDefaultTimeout()
+ Expect(ctr2.ExitCode()).To(Equal(0))
+ })
+
It("podman run --net container: copies hosts and resolv", func() {
SkipIfRootless()
ctrName := "ctr1"
diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go
index 5b4842fea..5ad8f9fb0 100644
--- a/test/e2e/run_staticip_test.go
+++ b/test/e2e/run_staticip_test.go
@@ -3,7 +3,10 @@
package integration
import (
+ "fmt"
+ "net/http"
"os"
+ "time"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
@@ -65,9 +68,20 @@ var _ = Describe("Podman run with --ip flag", func() {
It("Podman run two containers with the same IP", func() {
ip := GetRandomIPAddress()
- result := podmanTest.Podman([]string{"run", "-d", "--ip", ip, ALPINE, "sleep", "999"})
+ result := podmanTest.Podman([]string{"run", "-dt", "--ip", ip, nginx})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
+ for i := 0; i < 10; i++ {
+ fmt.Println("Waiting for nginx", err)
+ time.Sleep(1 * time.Second)
+ response, err := http.Get(fmt.Sprintf("http://%s", ip))
+ if err != nil {
+ continue
+ }
+ if response.StatusCode == http.StatusOK {
+ break
+ }
+ }
result = podmanTest.Podman([]string{"run", "-ti", "--ip", ip, ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 3eb93b84a..9b6de6f65 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -374,7 +374,9 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("1048576"))
+ if !cgroupsv2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2
+ Expect(session.OutputToString()).To(ContainSubstring("1048576"))
+ }
})
It("podman run device-write-bps test", func() {
@@ -392,7 +394,9 @@ var _ = Describe("Podman run", func() {
}
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("1048576"))
+ if !cgroupsv2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2
+ Expect(session.OutputToString()).To(ContainSubstring("1048576"))
+ }
})
It("podman run device-read-iops test", func() {
@@ -411,7 +415,9 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("100"))
+ if !cgroupsv2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2
+ Expect(session.OutputToString()).To(ContainSubstring("100"))
+ }
})
It("podman run device-write-iops test", func() {
@@ -430,7 +436,9 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("100"))
+ if !cgroupsv2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2
+ Expect(session.OutputToString()).To(ContainSubstring("100"))
+ }
})
It("podman run notify_socket", func() {
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 46c27dc2e..e31338dbc 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -15,6 +15,10 @@ import (
"github.com/onsi/gomega/gexec"
)
+var VolumeTrailingSlashDockerfile = `
+FROM alpine:latest
+VOLUME /test/`
+
var _ = Describe("Podman run with volumes", func() {
var (
tempdir string
@@ -421,4 +425,20 @@ var _ = Describe("Podman run with volumes", func() {
Expect(len(outputArr)).To(Equal(1))
Expect(strings.Contains(outputArr[0], fileName)).To(BeTrue())
})
+
+ It("Podman mount over image volume with trailing /", func() {
+ image := "podman-volume-test:trailing"
+ podmanTest.BuildImage(VolumeTrailingSlashDockerfile, image, "false")
+
+ ctrName := "testCtr"
+ create := podmanTest.Podman([]string{"create", "-v", "/tmp:/test", "--name", ctrName, image, "ls"})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ data := podmanTest.InspectContainer(ctrName)
+ Expect(len(data)).To(Equal(1))
+ Expect(len(data[0].Mounts)).To(Equal(1))
+ Expect(data[0].Mounts[0].Source).To(Equal("/tmp"))
+ Expect(data[0].Mounts[0].Destination).To(Equal("/test"))
+ })
})
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index d88231510..6d762d338 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -5,14 +5,13 @@ package integration
import (
"bytes"
"fmt"
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
"io/ioutil"
"os"
"strconv"
"text/template"
-
- . "github.com/containers/libpod/test/utils"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
)
type endpoint struct {
@@ -164,13 +163,6 @@ registries = ['{{.Host}}:{{.Port}}']`
}
})
- It("podman search v2 registry with empty query", func() {
- search := podmanTest.Podman([]string{"search", "registry.fedoraproject.org/"})
- search.WaitWithDefaultTimeout()
- Expect(search.ExitCode()).To(Equal(0))
- Expect(len(search.OutputToStringArray())).To(BeNumerically(">=", 1))
- })
-
It("podman search attempts HTTP if tls-verify flag is set false", func() {
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
@@ -225,6 +217,14 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search.ExitCode()).To(Equal(0))
Expect(search.OutputToString()).ShouldNot(BeEmpty())
+
+ // podman search v2 registry with empty query
+ searchEmpty := podmanTest.PodmanNoCache([]string{"search", fmt.Sprintf("%s/", registryEndpoints[3].Address()), "--tls-verify=false"})
+ searchEmpty.WaitWithDefaultTimeout()
+ Expect(searchEmpty.ExitCode()).To(BeZero())
+ Expect(len(searchEmpty.OutputToStringArray())).To(BeNumerically(">=", 1))
+ match, _ := search.GrepString("my-alpine")
+ Expect(match).Should(BeTrue())
})
It("podman search attempts HTTP if registry is in registries.insecure and force secure is false", func() {
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index 66ef53590..3224c9b42 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -74,4 +74,40 @@ size | [0-9]\\\+
run_podman rm my-container
}
+@test "podman images - filter" {
+ skip_if_remote "podman commit -q is broken in podman-remote"
+
+ run_podman inspect --format '{{.ID}}' $IMAGE
+ iid=$output
+
+ run_podman images --noheading --filter=after=$iid
+ is "$output" "" "baseline: empty results from filter (after)"
+
+ run_podman images --noheading --filter=before=$iid
+ is "$output" "" "baseline: empty results from filter (before)"
+
+ # Create a dummy container, then commit that as an image. We will
+ # now be able to use before/after/since queries
+ run_podman run --name mytinycontainer $IMAGE true
+ run_podman commit -q mytinycontainer mynewimage
+ new_iid=$output
+
+ # (refactor common options for legibility)
+ opts='--noheading --no-trunc --format={{.ID}}--{{.Repository}}:{{.Tag}}'
+
+ run_podman images ${opts} --filter=after=$iid
+ is "$output" "sha256:$new_iid--localhost/mynewimage:latest" "filter: after"
+
+ # Same thing, with 'since' instead of 'after'
+ run_podman images ${opts} --filter=since=$iid
+ is "$output" "sha256:$new_iid--localhost/mynewimage:latest" "filter: since"
+
+ run_podman images ${opts} --filter=before=mynewimage
+ is "$output" "sha256:$iid--$IMAGE" "filter: before"
+
+ # Clean up
+ run_podman rmi mynewimage
+ run_podman rm mytinycontainer
+}
+
# vim: filetype=sh
diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats
index 5e098d754..7c2b9bed8 100644
--- a/test/system/130-kill.bats
+++ b/test/system/130-kill.bats
@@ -6,10 +6,29 @@
load helpers
@test "podman kill - test signal handling in containers" {
+ # podman-remote and crun interact poorly in f31: crun seems to gobble up
+ # some signals.
+ # Workaround: run 'env --default-signal sh' instead of just 'sh' in
+ # the container. Since env on our regular alpine image doesn't support
+ # that flag, we need to pull fedora-minimal. See:
+ # https://github.com/containers/libpod/issues/5004
+ # FIXME: remove this kludge once we get rid of podman-remote
+ local _image=$IMAGE
+ local _sh_cmd="sh"
+ if is_remote; then
+ _image=quay.io/libpod/fedora-minimal:latest
+ _sh_cmd="env --default-signal sh"
+ fi
+
# Start a container that will handle all signals by emitting 'got: N'
local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64)
- run_podman run -d $IMAGE sh -c "for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done; echo READY; while ! test -e /stop; do sleep 0.05; done;echo DONE"
- cid="$output"
+ run_podman run -d $_image $_sh_cmd -c \
+ "for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done;
+ echo READY;
+ while ! test -e /stop; do sleep 0.05; done;
+ echo DONE"
+ # Ignore output regarding pulling/processing container images
+ cid=$(echo "$output" | tail -1)
# Run 'logs -f' on that container, but run it in the background with
# redirection to a named pipe from which we (foreground job) read
@@ -62,6 +81,10 @@ load helpers
run_podman wait $cid
run_podman rm $cid
wait $podman_log_pid
+
+ if [[ $_image != $IMAGE ]]; then
+ run_podman rmi $_image
+ fi
}
@test "podman kill - rejects invalid args" {
diff --git a/test/system/150-login.bats b/test/system/150-login.bats
new file mode 100644
index 000000000..e33217e14
--- /dev/null
+++ b/test/system/150-login.bats
@@ -0,0 +1,339 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# tests for podman login
+#
+
+load helpers
+
+###############################################################################
+# BEGIN one-time envariable setup
+
+# Create a scratch directory; our podman registry will run from here. We
+# also use it for other temporary files like authfiles.
+if [ -z "${PODMAN_LOGIN_WORKDIR}" ]; then
+ export PODMAN_LOGIN_WORKDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-${TMPDIR:-/tmp}} podman_bats_login.XXXXXX)
+fi
+
+# Randomly-generated username and password
+if [ -z "${PODMAN_LOGIN_USER}" ]; then
+ export PODMAN_LOGIN_USER="user$(random_string 4)"
+ export PODMAN_LOGIN_PASS=$(random_string 15)
+fi
+
+# Randomly-assigned port in the 5xxx range
+if [ -z "${PODMAN_LOGIN_REGISTRY_PORT}" ]; then
+ for port in $(shuf -i 5000-5999);do
+ if ! { exec 3<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
+ export PODMAN_LOGIN_REGISTRY_PORT=$port
+ break
+ fi
+ done
+fi
+
+# Override any user-set path to an auth file
+unset REGISTRY_AUTH_FILE
+
+# END one-time envariable setup
+###############################################################################
+# BEGIN filtering - none of these tests will work with podman-remote
+
+function setup() {
+ skip_if_remote "none of these tests work with podman-remote"
+
+ basic_setup
+}
+
+# END filtering - none of these tests will work with podman-remote
+###############################################################################
+# BEGIN first "test" - start a registry for use by other tests
+#
+# This isn't really a test: it's a helper that starts a local registry.
+# Note that we're careful to use a root/runroot separate from our tests,
+# so setup/teardown don't clobber our registry image.
+#
+
+@test "podman login [start registry]" {
+ AUTHDIR=${PODMAN_LOGIN_WORKDIR}/auth
+ mkdir -p $AUTHDIR
+
+ # Pull registry image, but into a separate container storage
+ mkdir -p ${PODMAN_LOGIN_WORKDIR}/root
+ mkdir -p ${PODMAN_LOGIN_WORKDIR}/runroot
+ PODMAN_LOGIN_ARGS="--root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot"
+ # Give it three tries, to compensate for flakes
+ run_podman ${PODMAN_LOGIN_ARGS} pull registry:2 ||
+ run_podman ${PODMAN_LOGIN_ARGS} pull registry:2 ||
+ run_podman ${PODMAN_LOGIN_ARGS} pull registry:2
+
+ # Registry image needs a cert. Self-signed is good enough.
+ CERT=$AUTHDIR/domain.crt
+ if [ ! -e $CERT ]; then
+ openssl req -newkey rsa:4096 -nodes -sha256 \
+ -keyout $AUTHDIR/domain.key -x509 -days 2 \
+ -out $AUTHDIR/domain.crt \
+ -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
+ fi
+
+ # Store credentials where container will see them
+ if [ ! -e $AUTHDIR/htpasswd ]; then
+ run_podman ${PODMAN_LOGIN_ARGS} run --rm \
+ --entrypoint htpasswd registry:2 \
+ -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} \
+ > $AUTHDIR/htpasswd
+
+ # In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
+ echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" \
+ > $AUTHDIR/htpasswd-plaintext
+ fi
+
+ # Run the registry container.
+ run_podman '?' ${PODMAN_LOGIN_ARGS} rm -f registry
+ run_podman ${PODMAN_LOGIN_ARGS} run -d \
+ -p ${PODMAN_LOGIN_REGISTRY_PORT}:5000 \
+ --name registry \
+ -v $AUTHDIR:/auth:Z \
+ -e "REGISTRY_AUTH=htpasswd" \
+ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
+ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
+ -e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
+ -e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
+ registry:2
+}
+
+# END first "test" - start a registry for use by other tests
+###############################################################################
+# BEGIN actual tests
+# BEGIN primary podman login/push/pull tests
+
+@test "podman login - basic test" {
+ run_podman login --tls-verify=false \
+ --username ${PODMAN_LOGIN_USER} \
+ --password-stdin \
+ localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
+ is "$output" "Login Succeeded!" "output from podman login"
+
+ # Now log out
+ run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
+ is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
+ "output from podman logout"
+}
+
+@test "podman login - with wrong credentials" {
+ registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
+
+ run_podman 125 login --tls-verify=false \
+ --username ${PODMAN_LOGIN_USER} \
+ --password-stdin \
+ $registry <<< "x${PODMAN_LOGIN_PASS}"
+ is "$output" \
+ "Error: error logging into \"$registry\": invalid username/password" \
+ 'output from podman login'
+}
+
+@test "podman login - check generated authfile" {
+ authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
+ rm -f $authfile
+
+ registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
+
+ run_podman login --authfile=$authfile \
+ --tls-verify=false \
+ --username ${PODMAN_LOGIN_USER} \
+ --password ${PODMAN_LOGIN_PASS} \
+ $registry
+
+ # Confirm that authfile now exists
+ test -e $authfile || \
+ die "podman login did not create authfile $authfile"
+
+ # Special bracket form needed because of colon in host:port
+ run jq -r ".[\"auths\"][\"$registry\"][\"auth\"]" <$authfile
+ is "$status" "0" "jq from $authfile"
+
+ expect_userpass="${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}"
+ actual_userpass=$(base64 -d <<<"$output")
+ is "$actual_userpass" "$expect_userpass" "credentials stored in $authfile"
+
+
+ # Now log out and make sure credentials are removed
+ run_podman logout --authfile=$authfile $registry
+
+ run jq -r '.auths' <$authfile
+ is "$status" "0" "jq from $authfile"
+ is "$output" "{}" "credentials removed from $authfile"
+}
+
+# Some push tests
+@test "podman push fail" {
+ # Create an invalid authfile
+ authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
+ rm -f $authfile
+
+ wrong_auth=$(base64 <<<"baduser:wrongpassword")
+ cat >$authfile <<EOF
+{
+ "auths": {
+ "localhost:${PODMAN_LOGIN_REGISTRY_PORT}": {
+ "auth": "$wrong_auth"
+ }
+ }
+}
+EOF
+
+ run_podman 125 push --authfile=$authfile \
+ --tls-verify=false $IMAGE \
+ localhost:${PODMAN_LOGIN_REGISTRY_PORT}/badpush:1
+ is "$output" ".*: unauthorized: authentication required" \
+ "auth error on push"
+}
+
+@test "podman push ok" {
+ # ARGH! We can't push $IMAGE (alpine_labels) to this registry; error is:
+ #
+ # Writing manifest to image destination
+ # Error: Error copying image to the remote destination: Error writing manifest: Error uploading manifest latest to localhost:${PODMAN_LOGIN_REGISTRY_PORT}/okpush: received unexpected HTTP status: 500 Internal Server Error
+ #
+ # Root cause: something to do with v1/v2 s1/s2:
+ #
+ # https://github.com/containers/skopeo/issues/651
+ #
+ run_podman pull busybox
+
+ # Preserve its ID for later comparison against push/pulled image
+ run_podman inspect --format '{{.Id}}' busybox
+ id_busybox=$output
+
+ destname=ok-$(random_string 10 | tr A-Z a-z)-ok
+ # Use command-line credentials
+ run_podman push --tls-verify=false \
+ --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
+ busybox localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
+
+ # Yay! Pull it back
+ run_podman pull --tls-verify=false \
+ --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
+ localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
+
+ # Compare to original busybox
+ run_podman inspect --format '{{.Id}}' $destname
+ is "$output" "$id_busybox" "Image ID of pulled image == busybox"
+
+ run_podman rmi busybox $destname
+}
+
+# END primary podman login/push/pull tests
+###############################################################################
+# BEGIN cooperation with skopeo
+
+# Skopeo helper - keep this separate, so we can test with different
+# envariable settings
+function _test_skopeo_credential_sharing() {
+ if ! type -p skopeo; then
+ skip "skopeo not available"
+ fi
+
+ registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
+
+ run_podman login "$@" --tls-verify=false \
+ --username ${PODMAN_LOGIN_USER} \
+ --password ${PODMAN_LOGIN_PASS} \
+ $registry
+
+ destname=skopeo-ok-$(random_string 10 | tr A-Z a-z)-ok
+ echo "# skopeo copy ..."
+ run skopeo copy "$@" \
+ --format=v2s2 \
+ --dest-tls-verify=false \
+ containers-storage:$IMAGE \
+ docker://$registry/$destname
+ echo "$output"
+ is "$status" "0" "skopeo copy - exit status"
+ is "$output" ".*Copying blob .*" "output of skopeo copy"
+ is "$output" ".*Copying config .*" "output of skopeo copy"
+ is "$output" ".*Writing manifest .*" "output of skopeo copy"
+
+ echo "# skopeo inspect ..."
+ run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
+ echo "$output"
+ is "$status" "0" "skopeo inspect - exit status"
+
+ got_name=$(jq -r .Name <<<"$output")
+ is "$got_name" "$registry/$dest_name" "skopeo inspect -> Name"
+
+ # Now try without a valid login; it should fail
+ run_podman logout "$@" $registry
+ echo "# skopeo inspect [with no credentials] ..."
+ run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
+ echo "$output"
+ is "$status" "1" "skopeo inspect - exit status"
+ is "$output" ".*: unauthorized: authentication required" \
+ "auth error on skopeo inspect"
+}
+
+@test "podman login - shares credentials with skopeo - default auth file" {
+ if is_rootless; then
+ if [ -z "${XDG_RUNTIME_DIR}" ]; then
+ skip "skopeo does not match podman when XDG_RUNTIME_DIR unset; #823"
+ fi
+ fi
+ _test_skopeo_credential_sharing
+}
+
+@test "podman login - shares credentials with skopeo - via envariable" {
+ skip "skopeo does not yet support REGISTRY_AUTH_FILE; #822"
+ authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
+ rm -f $authfile
+
+ REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing
+ rm -f $authfile
+}
+
+@test "podman login - shares credentials with skopeo - via --authfile" {
+ # Also test that command-line --authfile overrides envariable
+ authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
+ rm -f $authfile
+
+ fake_authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
+ rm -f $fake_authfile
+
+ REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing --authfile=$authfile
+
+ if [ -e $fake_authfile ]; then
+ die "REGISTRY_AUTH_FILE overrode command-line --authfile!"
+ fi
+ rm -f $authfile
+}
+
+# END cooperation with skopeo
+# END actual tests
+###############################################################################
+# BEGIN teardown (remove the registry container)
+
+@test "podman login [stop registry, clean up]" {
+ # For manual debugging; user may request keeping the registry running
+ if [ -n "${PODMAN_TEST_KEEP_LOGIN_REGISTRY}" ]; then
+ skip "[leaving registry running by request]"
+ fi
+
+ run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \
+ --runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
+ rm -f registry
+ run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \
+ --runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
+ rmi -a
+
+ # By default, clean up
+ if [ -z "${PODMAN_TEST_KEEP_LOGIN_WORKDIR}" ]; then
+ rm -rf ${PODMAN_LOGIN_WORKDIR}
+ fi
+
+ # Make sure socket is closed
+ if { exec 3<> /dev/tcp/127.0.0.1/${PODMAN_LOGIN_REGISTRY_PORT}; } &>/dev/null; then
+ die "Socket still seems open"
+ fi
+}
+
+# END teardown (remove the registry container)
+###############################################################################
+
+# vim: filetype=sh
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
new file mode 100644
index 000000000..cd836610b
--- /dev/null
+++ b/test/system/500-networking.bats
@@ -0,0 +1,63 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# Test podman local networking
+#
+
+load helpers
+
+# Copied from tsweeney's https://github.com/containers/libpod/issues/4827
+@test "podman networking: port on localhost" {
+ skip_if_remote
+ random_1=$(random_string 30)
+ random_2=$(random_string 30)
+
+ HOST_PORT=8080
+ SERVER=http://localhost:$HOST_PORT
+
+ # Create a test file with random content
+ INDEX1=$PODMAN_TMPDIR/hello.txt
+ echo $random_1 > $INDEX1
+
+ # Bind-mount this file with a different name to a container running httpd
+ run_podman run -d --name myweb -p "$HOST_PORT:80" \
+ -v $INDEX1:/var/www/index.txt \
+ -w /var/www \
+ busybox httpd -f -p 80
+ cid=$output
+
+ # In that container, create a second file, using exec and redirection
+ run_podman exec -i myweb sh -c "cat > index2.txt" <<<"$random_2"
+ # ...verify its contents as seen from container.
+ run_podman exec -i myweb cat /var/www/index2.txt
+ is "$output" "$random_2" "exec cat index2.txt"
+
+ # Verify http contents: curl from localhost
+ run curl -s $SERVER/index.txt
+ is "$output" "$random_1" "curl localhost:/index.txt"
+ run curl -s $SERVER/index2.txt
+ is "$output" "$random_2" "curl localhost:/index2.txt"
+
+ # Verify http contents: wget from a second container
+ run_podman run --rm --net=host busybox wget -qO - $SERVER/index.txt
+ is "$output" "$random_1" "podman wget /index.txt"
+ run_podman run --rm --net=host busybox wget -qO - $SERVER/index2.txt
+ is "$output" "$random_2" "podman wget /index2.txt"
+
+ # Tests #4889 - two-argument form of "podman ports" was broken
+ run_podman port myweb
+ is "$output" "80/tcp -> 0.0.0.0:$HOST_PORT" "port <cid>"
+ run_podman port myweb 80
+ is "$output" "0.0.0.0:$HOST_PORT" "port <cid> 80"
+ run_podman port myweb 80/tcp
+ is "$output" "0.0.0.0:$HOST_PORT" "port <cid> 80/tcp"
+
+ run_podman 125 port myweb 99/tcp
+ is "$output" 'Error: failed to find published port "99/tcp"'
+
+ # Clean up
+ run_podman stop -t 1 myweb
+ run_podman rm myweb
+ run_podman rmi busybox
+}
+
+# vim: filetype=sh
diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml
deleted file mode 100644
index 102fb9a69..000000000
--- a/vendor/github.com/blang/semver/.travis.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-language: go
-matrix:
- include:
- - go: 1.4.3
- - go: 1.5.4
- - go: 1.6.3
- - go: 1.7
- - go: tip
- allow_failures:
- - go: tip
-install:
-- go get golang.org/x/tools/cmd/cover
-- go get github.com/mattn/goveralls
-script:
-- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
- -repotoken $COVERALLS_TOKEN
-- echo "Build examples" ; cd examples && go build
-- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
-env:
- global:
- secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md
index 08b2e4a3d..4399639e2 100644
--- a/vendor/github.com/blang/semver/README.md
+++ b/vendor/github.com/blang/semver/README.md
@@ -1,4 +1,4 @@
-semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
+semver for golang [![Build Status](https://drone.io/github.com/blang/semver/status.png)](https://drone.io/github.com/blang/semver/latest) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
======
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
@@ -41,7 +41,6 @@ Features
- Compare Helper Methods
- InPlace manipulation
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
-- Wildcards `>=1.x`, `<=2.5.x`
- Sortable (implements sort.Interface)
- database/sql compatible (sql.Scanner/Valuer)
- encoding/json compatible (json.Marshaler/Unmarshaler)
@@ -60,8 +59,6 @@ A condition is composed of an operator and a version. The supported operators ar
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
-Note that spaces between the operator and the version will be gracefully tolerated.
-
A `Range` can link multiple `Ranges` separated by space:
Ranges can be linked by logical AND:
diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json
deleted file mode 100644
index 1cf8ebdd9..000000000
--- a/vendor/github.com/blang/semver/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "author": "blang",
- "bugs": {
- "URL": "https://github.com/blang/semver/issues",
- "url": "https://github.com/blang/semver/issues"
- },
- "gx": {
- "dvcsimport": "github.com/blang/semver"
- },
- "gxVersion": "0.10.0",
- "language": "go",
- "license": "MIT",
- "name": "semver",
- "releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
- "version": "3.5.1"
-}
-
diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go
index fca406d47..0a8eaa1c9 100644
--- a/vendor/github.com/blang/semver/range.go
+++ b/vendor/github.com/blang/semver/range.go
@@ -2,33 +2,10 @@ package semver
import (
"fmt"
- "strconv"
"strings"
"unicode"
)
-type wildcardType int
-
-const (
- noneWildcard wildcardType = iota
- majorWildcard wildcardType = 1
- minorWildcard wildcardType = 2
- patchWildcard wildcardType = 3
-)
-
-func wildcardTypefromInt(i int) wildcardType {
- switch i {
- case 1:
- return majorWildcard
- case 2:
- return minorWildcard
- case 3:
- return patchWildcard
- default:
- return noneWildcard
- }
-}
-
type comparator func(Version, Version) bool
var (
@@ -115,12 +92,8 @@ func ParseRange(s string) (Range, error) {
if err != nil {
return nil, err
}
- expandedParts, err := expandWildcardVersion(orParts)
- if err != nil {
- return nil, err
- }
var orFn Range
- for _, p := range expandedParts {
+ for _, p := range orParts {
var andFn Range
for _, ap := range p {
opStr, vStr, err := splitComparatorVersion(ap)
@@ -191,39 +164,20 @@ func buildVersionRange(opStr, vStr string) (*versionRange, error) {
}
-// inArray checks if a byte is contained in an array of bytes
-func inArray(s byte, list []byte) bool {
- for _, el := range list {
- if el == s {
- return true
- }
- }
- return false
-}
-
-// splitAndTrim splits a range string by spaces and cleans whitespaces
+// splitAndTrim splits a range string by spaces and cleans leading and trailing spaces
func splitAndTrim(s string) (result []string) {
last := 0
- var lastChar byte
- excludeFromSplit := []byte{'>', '<', '='}
for i := 0; i < len(s); i++ {
- if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
+ if s[i] == ' ' {
if last < i-1 {
result = append(result, s[last:i])
}
last = i + 1
- } else if s[i] != ' ' {
- lastChar = s[i]
}
}
if last < len(s)-1 {
result = append(result, s[last:])
}
-
- for i, v := range result {
- result[i] = strings.Replace(v, " ", "", -1)
- }
-
// parts := strings.Split(s, " ")
// for _, x := range parts {
// if s := strings.TrimSpace(x); len(s) != 0 {
@@ -234,6 +188,7 @@ func splitAndTrim(s string) (result []string) {
}
// splitComparatorVersion splits the comparator from the version.
+// Spaces between the comparator and the version are not allowed.
// Input must be free of leading or trailing spaces.
func splitComparatorVersion(s string) (string, string, error) {
i := strings.IndexFunc(s, unicode.IsDigit)
@@ -243,144 +198,6 @@ func splitComparatorVersion(s string) (string, string, error) {
return strings.TrimSpace(s[0:i]), s[i:], nil
}
-// getWildcardType will return the type of wildcard that the
-// passed version contains
-func getWildcardType(vStr string) wildcardType {
- parts := strings.Split(vStr, ".")
- nparts := len(parts)
- wildcard := parts[nparts-1]
-
- possibleWildcardType := wildcardTypefromInt(nparts)
- if wildcard == "x" {
- return possibleWildcardType
- }
-
- return noneWildcard
-}
-
-// createVersionFromWildcard will convert a wildcard version
-// into a regular version, replacing 'x's with '0's, handling
-// special cases like '1.x.x' and '1.x'
-func createVersionFromWildcard(vStr string) string {
- // handle 1.x.x
- vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
- vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
- parts := strings.Split(vStr2, ".")
-
- // handle 1.x
- if len(parts) == 2 {
- return vStr2 + ".0"
- }
-
- return vStr2
-}
-
-// incrementMajorVersion will increment the major version
-// of the passed version
-func incrementMajorVersion(vStr string) (string, error) {
- parts := strings.Split(vStr, ".")
- i, err := strconv.Atoi(parts[0])
- if err != nil {
- return "", err
- }
- parts[0] = strconv.Itoa(i + 1)
-
- return strings.Join(parts, "."), nil
-}
-
-// incrementMajorVersion will increment the minor version
-// of the passed version
-func incrementMinorVersion(vStr string) (string, error) {
- parts := strings.Split(vStr, ".")
- i, err := strconv.Atoi(parts[1])
- if err != nil {
- return "", err
- }
- parts[1] = strconv.Itoa(i + 1)
-
- return strings.Join(parts, "."), nil
-}
-
-// expandWildcardVersion will expand wildcards inside versions
-// following these rules:
-//
-// * when dealing with patch wildcards:
-// >= 1.2.x will become >= 1.2.0
-// <= 1.2.x will become < 1.3.0
-// > 1.2.x will become >= 1.3.0
-// < 1.2.x will become < 1.2.0
-// != 1.2.x will become < 1.2.0 >= 1.3.0
-//
-// * when dealing with minor wildcards:
-// >= 1.x will become >= 1.0.0
-// <= 1.x will become < 2.0.0
-// > 1.x will become >= 2.0.0
-// < 1.0 will become < 1.0.0
-// != 1.x will become < 1.0.0 >= 2.0.0
-//
-// * when dealing with wildcards without
-// version operator:
-// 1.2.x will become >= 1.2.0 < 1.3.0
-// 1.x will become >= 1.0.0 < 2.0.0
-func expandWildcardVersion(parts [][]string) ([][]string, error) {
- var expandedParts [][]string
- for _, p := range parts {
- var newParts []string
- for _, ap := range p {
- if strings.Index(ap, "x") != -1 {
- opStr, vStr, err := splitComparatorVersion(ap)
- if err != nil {
- return nil, err
- }
-
- versionWildcardType := getWildcardType(vStr)
- flatVersion := createVersionFromWildcard(vStr)
-
- var resultOperator string
- var shouldIncrementVersion bool
- switch opStr {
- case ">":
- resultOperator = ">="
- shouldIncrementVersion = true
- case ">=":
- resultOperator = ">="
- case "<":
- resultOperator = "<"
- case "<=":
- resultOperator = "<"
- shouldIncrementVersion = true
- case "", "=", "==":
- newParts = append(newParts, ">="+flatVersion)
- resultOperator = "<"
- shouldIncrementVersion = true
- case "!=", "!":
- newParts = append(newParts, "<"+flatVersion)
- resultOperator = ">="
- shouldIncrementVersion = true
- }
-
- var resultVersion string
- if shouldIncrementVersion {
- switch versionWildcardType {
- case patchWildcard:
- resultVersion, _ = incrementMinorVersion(flatVersion)
- case minorWildcard:
- resultVersion, _ = incrementMajorVersion(flatVersion)
- }
- } else {
- resultVersion = flatVersion
- }
-
- ap = resultOperator + resultVersion
- }
- newParts = append(newParts, ap)
- }
- expandedParts = append(expandedParts, newParts)
- }
-
- return expandedParts, nil
-}
-
func parseComparator(s string) comparator {
switch s {
case "==":
@@ -405,12 +222,3 @@ func parseComparator(s string) comparator {
return nil
}
-
-// MustParseRange is like ParseRange but panics if the range cannot be parsed.
-func MustParseRange(s string) Range {
- r, err := ParseRange(s)
- if err != nil {
- panic(`semver: ParseRange(` + s + `): ` + err.Error())
- }
- return r
-}
diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go
index 8ee0842e6..bbf85ce97 100644
--- a/vendor/github.com/blang/semver/semver.go
+++ b/vendor/github.com/blang/semver/semver.go
@@ -200,29 +200,6 @@ func Make(s string) (Version, error) {
return Parse(s)
}
-// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
-// specs to be parsed by this library. It does so by normalizing versions before passing them to
-// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
-// with only major and minor components specified
-func ParseTolerant(s string) (Version, error) {
- s = strings.TrimSpace(s)
- s = strings.TrimPrefix(s, "v")
-
- // Split into major.minor.(patch+pr+meta)
- parts := strings.SplitN(s, ".", 3)
- if len(parts) < 3 {
- if strings.ContainsAny(parts[len(parts)-1], "+-") {
- return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
- }
- for len(parts) < 3 {
- parts = append(parts, "0")
- }
- s = strings.Join(parts, ".")
- }
-
- return Parse(s)
-}
-
// Parse parses version string and returns a validated Version or error
func Parse(s string) (Version, error) {
if len(s) == 0 {
diff --git a/vendor/github.com/containers/buildah/.cirrus.yml b/vendor/github.com/containers/buildah/.cirrus.yml
index 66774c226..65bbd31ff 100644
--- a/vendor/github.com/containers/buildah/.cirrus.yml
+++ b/vendor/github.com/containers/buildah/.cirrus.yml
@@ -5,24 +5,33 @@ env:
####
#### Global variables used for all tasks
####
+ # Name of the ultimate destination branch for this CI run, PR or post-merge.
+ DEST_BRANCH: "master"
+ GOPATH: "/var/tmp/go"
+ GOSRC: "${GOPATH}/src/github.com/containers/buildah"
# Overrides default location (/tmp/cirrus) for repo clone
- CIRRUS_WORKING_DIR: "/var/tmp/go/src/github.com/containers/buildah"
+ CIRRUS_WORKING_DIR: "${GOSRC}"
# Shell used to execute all script commands
CIRRUS_SHELL: "/bin/bash"
# Automation script path relative to $CIRRUS_WORKING_DIR)
SCRIPT_BASE: "./contrib/cirrus"
# No need to go crazy, but grab enough to cover most PRs
CIRRUS_CLONE_DEPTH: 50
+ # Unless set by in_podman.sh, default to operating outside of a podman container
+ IN_PODMAN: 'false'
+ # Not cross-compiling by default
+ CROSS_TARGET: ""
####
#### Cache-image names to test with
####
# GCE project where images live
IMAGE_PROJECT: "libpod-218412"
+ # TODO: Setting up from base-images is very inefficient, use libpod's cache-images instead?
FEDORA_CACHE_IMAGE_NAME: "fedora-cloud-base-30-1-2-1565360543"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-cloud-base-29-1-2-1565360543"
- UBUNTU_CACHE_IMAGE_NAME: "ubuntu-1904-disco-v20190724" # Latest
- PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-1804-bionic-v20190722a" # LTS
+ UBUNTU_CACHE_IMAGE_NAME: "ubuntu-1904-disco-v20190724"
+ PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-1804-bionic-v20190722a"
####
#### Command variables to help avoid duplication
@@ -30,10 +39,6 @@ env:
# Command to prefix every output line with a timestamp
# (can't do inline awk script, Cirrus-CI or YAML mangles quoting)
_TIMESTAMP: 'awk -f ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/timestamp.awk'
- _DFCMD: 'df -lhTx tmpfs'
- _RAUDITCMD: 'cat /var/log/audit/audit.log'
- _UAUDITCMD: 'cat /var/log/kern.log'
- _JOURNALCMD: 'journalctl -b'
gcp_credentials: ENCRYPTED[ae0bf7370f0b6e446bc61d0865a2c55d3e166b3fab9466eb0393e38e1c66a31ca4c71ddc7e0139d47d075c36dd6d3fd7]
@@ -50,43 +55,81 @@ gce_instance:
image_name: "${FEDORA_CACHE_IMAGE_NAME}"
-testing_task:
- gce_instance: # Only need to specify differences from defaults (above)
- matrix: # Duplicate this task for each matrix product.
- image_name: "${FEDORA_CACHE_IMAGE_NAME}"
- image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
- image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
- image_name: "${PRIOR_UBUNTU_CACHE_IMAGE_NAME}"
+# Update metadata on VM images referenced by this repository state
+'cirrus-ci/only_prs/meta_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ container:
+ image: "quay.io/libpod/imgts:latest" # see contrib/imgts
+ cpu: 1
+ memory: 1
+
+ env:
+ # Space-separated list of images used by this repository state
+ IMGNAMES: |-
+ ${FEDORA_CACHE_IMAGE_NAME}
+ ${PRIOR_FEDORA_CACHE_IMAGE_NAME}
+ ${UBUNTU_CACHE_IMAGE_NAME}
+ ${PRIOR_UBUNTU_CACHE_IMAGE_NAME}
+ BUILDID: "${CIRRUS_BUILD_ID}"
+ REPOREF: "${CIRRUS_CHANGE_IN_REPO}"
+ GCPJSON: ENCRYPTED[d3614d6f5cc0e66be89d4252b3365fd84f14eee0259d4eb47e25fc0bc2842c7937f5ee8c882b7e547b4c5ec4b6733b14]
+ GCPNAME: ENCRYPTED[8509e6a681b859479ce6aa275bd3c4ac82de5beec6df6057925afc4cd85b7ef2e879066ae8baaa2d453b82958e434578]
+ GCPPROJECT: ENCRYPTED[cc09b62d0ec6746a3df685e663ad25d9d5af95ef5fd843c96f3d0ec9d7f065dc63216b9c685c9f43a776a1d403991494]
+ CIRRUS_CLONE_DEPTH: 1 # source not used
+
+ script: '/usr/local/bin/entrypoint.sh |& ${_TIMESTAMP}'
- # Separate scripts for separate outputs, makes debugging easier.
- setup_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
- build_and_test_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/build_and_test.sh |& ${_TIMESTAMP}'
- # Log collection when job was successful
- df_script: '${_DFCMD} || true'
- rh_audit_log_script: '${_RAUDITCMD} || true'
- ubuntu_audit_log_script: '${_UAUDITCMD} || true'
- journal_log_script: '${_JOURNALCMD} || true'
+'cirrus-ci/only_prs/gate_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ timeout_in: 30m
- on_failure: # Script names must be different from above
- failure_df_script: '${_DFCMD} || true'
- failure_rh_audit_log_script: '${_RAUDITCMD} || true'
- failure_ubuntu_audit_log_script: '${_UAUDITCMD} || true'
- failure_journal_log_script: '${_JOURNALCMD} || true'
+ setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
+ build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
+ validate_test_script: '${SCRIPT_BASE}/test.sh validate |& ${_TIMESTAMP}'
+
+ binary_artifacts:
+ path: ./bin/*
+
+
+'cirrus-ci/only_prs/unit_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ # not supported by bors-ng
+ # allow_failures: $CI == $CI
+
+ timeout_in: 30m
+
+ setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
+ build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
+ # FIXME: These tests mostly/always fail
+ unit_test_script: '${SCRIPT_BASE}/test.sh unit |& ${_TIMESTAMP} || true'
+
+ binary_artifacts:
+ path: ./bin/*
# 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
# that the vendor.conf, the code and the vendored packages in ./vendor are
# in sync at all times.
-vendor_task:
+'cirrus-ci/only_prs/vendor_task':
- only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\*\*\*\s*CIRRUS:\s*TEST\s*IMAGES\s*\*\*\*.*'
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
env:
CIRRUS_WORKING_DIR: "/var/tmp/go/src/github.com/containers/buildah"
- GOPATH: "/go"
- GOSRC: "/go/src/github.com/containers/buildah"
+ GOPATH: "/var/tmp/go"
+ GOSRC: "/var/tmp/go/src/github.com/containers/buildah"
# Runs within Cirrus's "community cluster"
container:
@@ -94,35 +137,118 @@ vendor_task:
cpu: 1
memory: 1
- timeout_in: 30m
+ timeout_in: 5m
vendor_script:
- - 'cd ${CIRRUS_WORKING_DIR} && make vendor'
- - 'cd ${CIRRUS_WORKING_DIR} && ./hack/tree_status.sh'
+ - 'make vendor'
+ - './hack/tree_status.sh'
-# Update metadata on VM images referenced by this repository state
-meta_task:
+
+'cirrus-ci/only_prs/cross_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
depends_on:
- - "vendor"
+ - 'cirrus-ci/only_prs/gate'
+ - 'cirrus-ci/only_prs/vendor'
container:
- image: "quay.io/libpod/imgts:latest" # see contrib/imgts
- cpu: 1
- memory: 1
+ image: registry.fedoraproject.org/fedora:30
env:
- # Space-separated list of images used by this repository state
- IMGNAMES: |-
- ${FEDORA_CACHE_IMAGE_NAME}
- ${PRIOR_FEDORA_CACHE_IMAGE_NAME}
- ${UBUNTU_CACHE_IMAGE_NAME}
- ${PRIOR_UBUNTU_CACHE_IMAGE_NAME}
- BUILDID: "${CIRRUS_BUILD_ID}"
- REPOREF: "${CIRRUS_CHANGE_IN_REPO}"
- GCPJSON: ENCRYPTED[d3614d6f5cc0e66be89d4252b3365fd84f14eee0259d4eb47e25fc0bc2842c7937f5ee8c882b7e547b4c5ec4b6733b14]
- GCPNAME: ENCRYPTED[8509e6a681b859479ce6aa275bd3c4ac82de5beec6df6057925afc4cd85b7ef2e879066ae8baaa2d453b82958e434578]
- GCPPROJECT: ENCRYPTED[cc09b62d0ec6746a3df685e663ad25d9d5af95ef5fd843c96f3d0ec9d7f065dc63216b9c685c9f43a776a1d403991494]
- CIRRUS_CLONE_DEPTH: 1 # source not used
+ matrix:
+ CROSS_TARGET: darwin
- script: '/usr/local/bin/entrypoint.sh |& ${_TIMESTAMP}'
+ setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
+ build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
+
+ binary_artifacts:
+ path: ./bin/*
+
+
+'cirrus-ci/required/testing_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ depends_on:
+ - 'cirrus-ci/only_prs/gate'
+ - 'cirrus-ci/only_prs/vendor'
+
+ gce_instance: # Only need to specify differences from defaults (above)
+ matrix: # Duplicate this task for each matrix product.
+ image_name: "${FEDORA_CACHE_IMAGE_NAME}"
+ # TODO: Re-enable once prior image is F30 and above is F31
+ # image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
+ image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
+ image_name: "${PRIOR_UBUNTU_CACHE_IMAGE_NAME}"
+
+ # Separate scripts for separate outputs, makes debugging easier.
+ setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
+ build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
+ integration_test_script: '${SCRIPT_BASE}/test.sh integration |& ${_TIMESTAMP}'
+
+ binary_artifacts:
+ path: ./bin/*
+
+ always: &standardlogs
+ audit_log_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh audit'
+ df_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh df'
+ journal_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh journal'
+ podman_system_info_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh podman'
+ buildah_version_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh buildah_version'
+ buildah_info_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh buildah_info'
+ package_versions_script: '$GOSRC/$SCRIPT_BASE/logcollector.sh packages'
+
+
+'cirrus-ci/required/in_podman_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ depends_on:
+ - 'cirrus-ci/only_prs/gate'
+ - 'cirrus-ci/only_prs/vendor'
+
+ env:
+ # This is key, it causes the scripts to re-execute themselves inside a container.
+ IN_PODMAN: 'true'
+ BUILDAH_ISOLATION: 'chroot'
+ STORAGE_DRIVER: 'vfs'
+ STORAGE_OPTIONS: ''
+
+ # Separate scripts for separate outputs, makes debugging easier.
+ setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
+ build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
+ integration_test_script: '${SCRIPT_BASE}/test.sh integration |& ${_TIMESTAMP}'
+
+ binary_artifacts:
+ path: ./bin/*
+
+ always:
+ <<: *standardlogs
+
+# TODO: Bors-ng has trouble interpreting multiple status-checks as being required
+# when their names contain wild-cards (like `testing%`). Until that issue
+# can be fixed, use a single "test" to represent pass/fail status of all
+# required checks.
+'cirrus-ci/success_task':
+
+ # see bors.toml
+ skip: $CIRRUS_BRANCH =~ ".*\.tmp"
+
+ depends_on:
+ - "cirrus-ci/required/testing"
+ - "cirrus-ci/required/in_podman"
+
+ env:
+ CIRRUS_WORKING_DIR: /tmp
+ CIRRUS_CLONE_DEPTH: 1 # no code is being used by this task
+
+ container:
+ image: "registry.fedoraproject.org/fedora-minimal:latest"
+ cpu: 1
+ memory: 1
+
+ script: /bin/true
diff --git a/vendor/github.com/containers/buildah/.papr.sh b/vendor/github.com/containers/buildah/.papr.sh
deleted file mode 100644
index 2795e9ec0..000000000
--- a/vendor/github.com/containers/buildah/.papr.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-set -xeuo pipefail
-export GOPATH=/go
-export PATH=$HOME/gopath/bin:$PATH:$GOPATH/bin
-export GOSRC=$GOPATH/src/github.com/containers/buildah
-
-cp -fv /etc/yum.repos.d{.host/*.repo,}
-
-dnf install -y \
- bats \
- btrfs-progs-devel \
- bzip2 \
- device-mapper-devel \
- findutils \
- git \
- glib2-devel \
- glibc-static \
- gnupg \
- golang \
- gpgme-devel \
- libassuan-devel \
- libseccomp-devel \
- libselinux-devel \
- libselinux-static \
- libseccomp-static \
- libselinux-utils \
- make \
- openssl \
- skopeo-containers \
- which
-
-
-# Install gomega
-go get github.com/onsi/gomega/...
-
-# PAPR adds a merge commit, for testing, which fails the
-# short-commit-subject validation test, so tell git-validate.sh to only check
-# up to, but not including, the merge commit.
-export GITVALIDATE_TIP=$(cd $GOSRC; git log -2 --pretty='%H' | tail -n 1)
-make -C $GOSRC install.tools runc all validate test-unit test-integration static
-env BUILDAH_ISOLATION=chroot make -C $GOSRC test-integration
-env BUILDAH_ISOLATION=rootless make -C $GOSRC test-integration
diff --git a/vendor/github.com/containers/buildah/.papr.yml b/vendor/github.com/containers/buildah/.papr.yml
deleted file mode 100644
index 4be12a18e..000000000
--- a/vendor/github.com/containers/buildah/.papr.yml
+++ /dev/null
@@ -1,87 +0,0 @@
-branches:
- - master
- - auto
- - try
-
-host:
- # 29 is the highest level of atomic
- distro: fedora/29/atomic
-
-required: true
-
-tests:
- # Let's create a self signed certificate and get it in the right places
- - hostname
- - ip a
- - ping -c 3 localhost
- - cat /etc/hostname
- - mkdir -p /home/travis/auth
- - openssl req -newkey rsa:4096 -nodes -sha256 -keyout /home/travis/auth/domain.key -x509 -days 2 -out /home/travis/auth/domain.crt -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
- - cp /home/travis/auth/domain.crt /home/travis/auth/domain.cert
- - sudo mkdir -p /etc/docker/certs.d/docker.io/
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/docker.io/ca.crt
- - sudo mkdir -p /etc/docker/certs.d/localhost:5000/
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/localhost:5000/ca.crt
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/localhost:5000/domain.crt
- # Create the credentials file, then start up the Docker registry
- - podman run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > /home/travis/auth/htpasswd
- - podman run -d -p 5000:5000 --name registry -v /home/travis/auth:/home/travis/auth:Z -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/home/travis/auth/htpasswd -e REGISTRY_HTTP_TLS_CERTIFICATE=/home/travis/auth/domain.crt -e REGISTRY_HTTP_TLS_KEY=/home/travis/auth/domain.key registry:2
-
-# Test Podman setup
- - podman version
- - podman info
- - podman ps --all
- - podman images
- - ls -alF /home/travis/auth
- - podman pull alpine
- - podman login localhost:5000 --username testuser --password testpassword
- - podman tag alpine localhost:5000/my-alpine
- - podman push --creds=testuser:testpassword localhost:5000/my-alpine
- - podman ps --all
- - podman images
- - podman rmi docker.io/alpine
- - podman rmi localhost:5000/my-alpine
- - podman pull --creds=testuser:testpassword localhost:5000/my-alpine
- - podman ps --all
- - podman images
- - podman rmi localhost:5000/my-alpine
-
- # mount yum repos to inherit injected mirrors from PAPR
- - podman run --net=host --security-opt label=disable --cap-add all --security-opt seccomp=unconfined -v /etc/yum.repos.d:/etc/yum.repos.d.host:ro
- -v $PWD:/go/src/github.com/containers/buildah
- --workdir /go/src/github.com/containers/buildah
- registry.fedoraproject.org/fedora:30 bash -c sh ./.papr.sh
-
----
-
-container:
- image: registry.fedoraproject.org/fedora:30
-
-packages:
- - btrfs-progs-devel
- - bzip2
- - device-mapper-devel
- - findutils
- - git
- - glib2-devel
- - gnupg
- - golang
- - libassuan-devel
- - make
- - skopeo-containers
-
-required: false
-pulls: true
-
-env:
- GOPATH: /go
- GOSRC: /go/src/github.com/containers
-
-tests:
- - mkdir -p $GOSRC && ln -s /var/tmp/checkout $GOSRC/buildah
- - cd $GOSRC/buildah && make darwin
-
-artifacts:
- - test-suite.log
-
-context: "darwin CI"
diff --git a/vendor/github.com/containers/buildah/.travis.yml b/vendor/github.com/containers/buildah/.travis.yml
deleted file mode 100644
index 04b665611..000000000
--- a/vendor/github.com/containers/buildah/.travis.yml
+++ /dev/null
@@ -1,95 +0,0 @@
-language: go
-dist: xenial
-sudo: required
-go:
- - 1.13.x
- - tip
-go_import_path: github.com/containers/buildah
-
-env:
- global:
- - TRAVIS_ENV="-e TRAVIS=$TRAVIS
- -e CI=$CI
- -e TRAVIS_COMMIT=$TRAVIS_COMMIT
- -e TRAVIS_COMMIT_RANGE=$TRAVIS_COMMIT_RANGE
- -e TRAVIS_REPO_SLUG=$TRAVIS_REPO_SLUG
- -e TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST
- -e TRAVIS_PULL_REQUEST_SHA=$TRAVIS_PULL_REQUEST_SHA
- -e TRAVIS_PULL_REQUEST_SLUG=$TRAVIS_PULL_REQUEST_SLUG
- -e TRAVIS_BRANCH=$TRAVIS_BRANCH
- -e TRAVIS_JOB_ID=$TRAVIS_JOB_ID
- -e TRAVIS_BUILD_DIR=$TRAVIS_BUILD_DIR"
- matrix:
- - BUILDAH_ISOLATION=oci
- DISTRO="ubuntu"
- - BUILDAH_ISOLATION=chroot
- DISTRO="ubuntu"
- - BUILDAH_ISOLATION=rootless
- DISTRO="ubuntu"
-matrix:
- # If the latest unstable development version of go fails, that's OK.
- allow_failures:
- - go: tip
- - env: TEST_GROUP=conformance
-
- # Don't hold on the tip tests to finish. Mark tests green if the
- # stable versions pass.
- fast_finish: true
-
-services:
- - docker
-before_install:
- - sudo apt-get -qq install software-properties-common
- - sudo add-apt-repository -y ppa:duggan/bats
- - sudo apt-get update
- - sudo apt-get -qq install bats btrfs-tools git libapparmor-dev libc-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libselinux1-dev linux-libc-dev realpath e2fslibs-dev libfuse-dev codespell
- - sudo apt-get -qq update
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
- - mkdir /home/travis/auth
- - sudo mkdir -p /var/lib/containers/storage/overlay
-install:
- # Let's create a self signed certificate and get it in the right places
- - hostname
- - ip a
- - ping -c 3 localhost
- - cat /etc/hostname
- - openssl req -newkey rsa:4096 -nodes -sha256 -keyout /home/travis/auth/domain.key -x509 -days 2 -out /home/travis/auth/domain.crt -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
- - cp /home/travis/auth/domain.crt /home/travis/auth/domain.cert
- - sudo mkdir -p /etc/docker/certs.d/docker.io/
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/docker.io/ca.crt
- - sudo mkdir -p /etc/docker/certs.d/localhost:5000/
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/localhost:5000/ca.crt
- - sudo cp /home/travis/auth/domain.crt /etc/docker/certs.d/localhost:5000/domain.crt
- # Create the credentials file, then start up the Docker registry
- - docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > /home/travis/auth/htpasswd
- - docker run -d -p 5000:5000 --name registry -v /home/travis/auth:/home/travis/auth:Z -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/home/travis/auth/htpasswd -e REGISTRY_HTTP_TLS_CERTIFICATE=/home/travis/auth/domain.crt -e REGISTRY_HTTP_TLS_KEY=/home/travis/auth/domain.key registry:2
-script:
- # Fail fast
- - set -e
- # Let's do some docker stuff just for verification purposes
-# Commented out the following in order to get travis runs
-# under the 50 minute requirement. Do not remove as we may
-# want to use this in cirrius testing when we move there.
-# - docker ps --all
-# - docker images
-# - ls -alF /home/travis/auth
-# - docker pull docker.io/alpine
-# - echo testpassword | docker login localhost:5000 --username testuser --password-stdin
-# - docker tag alpine localhost:5000/my-alpine
-# - docker push localhost:5000/my-alpine
-# - docker ps --all
-# - docker images
-# - docker rmi docker.io/alpine
-# - docker rmi localhost:5000/my-alpine
-# - docker pull localhost:5000/my-alpine
-# - docker ps --all
-# - docker images
-# - docker rmi localhost:5000/my-alpine
-# End Speed up comment
- # Setting up Docker Registry is complete, let's do Buildah testing!
- - make install.tools -j4
- - make install.libseccomp.sudo all runc validate lint SECURITYTAGS="apparmor seccomp"
- - go test -c -tags "apparmor seccomp `./btrfs_tag.sh` `./libdm_tag.sh` `./selinux_tag.sh`" ./cmd/buildah
- - tmp=`mktemp -d`; mkdir $tmp/root $tmp/runroot; sudo PATH="$PATH" ./buildah.test -test.v --root $tmp/root --runroot $tmp/runroot --storage-driver vfs --signature-policy `pwd`/tests/policy.json --registries-conf `pwd`/tests/registries.conf
- - cd tests; sudo PATH="$PATH" ./test_runner.sh
- - cd ..
diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md
index 30dd0dc04..3122e90a7 100644
--- a/vendor/github.com/containers/buildah/CHANGELOG.md
+++ b/vendor/github.com/containers/buildah/CHANGELOG.md
@@ -2,8 +2,41 @@
# Changelog
+## v1.14.0 (2020-02-05)
+ bump github.com/mtrmac/gpgme
+ Update containers/common to v0.1.4
+ manifest push: add --format option
+ Bump github.com/onsi/gomega from 1.8.1 to 1.9.0
+ vendor github.com/containers/image/v5@v5.2.0
+ info test: deal with random key order
+ Bump back to v1.14.0-dev
+
+## v1.13.2 (2020-01-29)
+ sign.bats: set GPG_TTY=/dev/null
+ Fix parse_unsupported.go
+ getDateAndDigestAndSize(): use manifest.Digest
+ Bump github.com/opencontainers/selinux from 1.3.0 to 1.3.1
+ Bump github.com/containers/common from 0.1.0 to 0.1.2
+ Touch up os/arch doc
+ chroot: handle slightly broken seccomp defaults
+ buildahimage: specify fuse-overlayfs mount options
+ Bump github.com/mattn/go-shellwords from 1.0.7 to 1.0.9
+ copy.bats: make sure we detect failures due to missing source
+ parse: don't complain about not being able to rename something to itself
+ Makefile: use a $(GO_TEST) macro, fix a typo
+ manifests: unit test fix
+ Fix build for 32bit platforms
+ Allow users to set OS and architecture on bud
+ Fix COPY in containerfile with envvar
+ Bump c/storage to v1.15.7
+ add --sign-by to bud/commit/push, --remove-signatures for pull/push
+ Remove cut/paste error in CHANGELOG.md
+ Update vendor of containers/common to v0.1.0
+ update install instructions for Debian, Raspbian and Ubuntu
+ Add support for containers.conf
+ Bump back to v1.14.0-dev
+
## v1.13.1 (2020-01-14)
-Changelog for v1.13.1 (2020-01-14)
Bump github.com/containers/common from 0.0.5 to 0.0.7
Bump github.com/onsi/ginkgo from 1.10.3 to 1.11.0
Bump github.com/pkg/errors from 0.8.1 to 0.9.0
@@ -25,23 +58,6 @@ Changelog for v1.13.1 (2020-01-14)
discard outputs coming from onbuild command on buildah-from --quiet
make --format columnizing consistent with buildah images
Bump to v1.14.0-dev
- Bump to v1.13.0
- Bump to c/storage v1.15.5
- Update container/storage to v1.15.4
- Fix option handling for volumes in build
- Rework overlay pkg for use with libpod
- Fix buildahimage builds for buildah
- Add support for FIPS-Mode backends
- Set the TMPDIR for pulling/pushing image to $TMPDIR
- WIP: safer test for pull --all-tags
- BATS major cleanup: blobcache.bats: refactor
- BATS major cleanup: part 4: manual stuff
- BATS major cleanup, step 3: yet more run_buildah
- BATS major cleanup, part 2: use more run_buildah
- BATS major cleanup, part 1: log-level
- Bump github.com/containers/image/v5 from 5.0.0 to 5.1.0
- Bump github.com/containers/common from 0.0.3 to 0.0.5
- Bump to v1.13.0-dev
## v1.13.0 (2019-12-27)
Bump to c/storage v1.15.5
diff --git a/vendor/github.com/containers/buildah/CODE-OF-CONDUCT.md b/vendor/github.com/containers/buildah/CODE-OF-CONDUCT.md
new file mode 100644
index 000000000..247674cce
--- /dev/null
+++ b/vendor/github.com/containers/buildah/CODE-OF-CONDUCT.md
@@ -0,0 +1,3 @@
+## The Buildah Project Community Code of Conduct
+
+The Buildah Project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
diff --git a/vendor/github.com/containers/buildah/CONTRIBUTING.md b/vendor/github.com/containers/buildah/CONTRIBUTING.md
index 8118a240b..0178a517c 100644
--- a/vendor/github.com/containers/buildah/CONTRIBUTING.md
+++ b/vendor/github.com/containers/buildah/CONTRIBUTING.md
@@ -10,6 +10,7 @@ that we follow.
* [Reporting Issues](#reporting-issues)
* [Submitting Pull Requests](#submitting-pull-requests)
* [Sign your PRs](#sign-your-prs)
+* [Merge bot interaction](#merge-bot-interaction)
* [Communications](#communications)
* [Becoming a Maintainer](#becoming-a-maintainer)
@@ -116,6 +117,57 @@ Use your real name (sorry, no pseudonyms or anonymous contributions.)
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.
+## Merge bot interaction
+
+Maintainers should never merge anything directly into upstream
+branches. Instead, interact with the [bors-ng bot](https://bors.tech/)
+through PR comments as summarized below. This ensures all upstream
+branches contain commits in a predictable order, and that every commit
+has passed automated testing at some point in the past. A
+[Maintainer portal](https://app.bors.tech/repositories/22803)
+is available, showing all PRs awaiting review and approval.
+
+### Common [bors-ng comment commands](https://bors.tech/documentation/):
+
+(must be on a single comment-line, without any other extraneous text)
+
+* `bors r+` - Check the current number of Github Code-review Approvals.
+ If the PR has that many approvals or more, the bot will add the PR into
+ the queue for testing and possible merging. Both the success criteria
+ and minimum approval number are set in the configuration file (see below).
+* `bors retry` - Re-run whatever request was previously issued to the bot. Useful
+ when there was a testing flake upon attempted merge.
+* `bors try` - Optional / simulate the actions of `bors r+` (see above) having
+ met the minimum number of required approvals. The result will be reported
+ back as a comment in the PR, by the bors bot.
+* `bors ping` - Confirm bot is functioning, it will post a comment in the PR if so.
+
+
+### Interaction/Monitoring
+
+Bors-ng relies on the regular branch-testing occurring when it updates the
+special branches ('trying' or 'staging'). Therefore you may use the full
+capabilities available within the CI system. ***Note:*** A single bors-ng
+run may include multiple PRs at once.
+
+The easiest way to access a running 'bors try' or 'bors r+' run, is by clicking the
+yellow-circle "status" icon that shows up in an affected PR, for example:
+
+![Screenshot of Github PR](contrib/cirrus/bors-ng.png)
+
+This will cause a pop-up window to appear with the relevant test-statuses and 'details'
+links available. Since bors-ng will wait for success, as long as one test is still
+running, it's possible to manually re-run any failed tests (e.g. due to flakes).
+
+
+### Configuration of bors-ng:
+
+* The `bors.toml` file in the repository root. This controls
+ runtime options for timeouts, blocking labels, and required status names.
+* The [settings page](https://app.bors.tech/repositories/22803/settings).
+ This contains mostly security-related and branch-control options.
+
+
## Communications
For general questions or discussions, please use the
diff --git a/vendor/github.com/containers/buildah/Makefile b/vendor/github.com/containers/buildah/Makefile
index 2e4eb61c4..928a2e64d 100644
--- a/vendor/github.com/containers/buildah/Makefile
+++ b/vendor/github.com/containers/buildah/Makefile
@@ -18,8 +18,10 @@ GOVERSION := $(findstring $(GO110),$(shell go version))
# test for go module support
ifeq ($(shell go help mod >/dev/null 2>&1 && echo true), true)
export GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
+export GO_TEST=GO111MODULE=on $(GO) test -mod=vendor
else
export GO_BUILD=$(GO) build
+export GO_TEST=$(GO) test
endif
GIT_COMMIT ?= $(if $(shell git rev-parse --short HEAD),$(shell git rev-parse --short HEAD),$(error "git failed"))
@@ -35,6 +37,8 @@ EXTRALDFLAGS :=
LDFLAGS := -ldflags '-X main.GitCommit=$(GIT_COMMIT) -X main.buildInfo=$(SOURCE_DATE_EPOCH) -X main.cniVersion=$(CNI_COMMIT)' $(EXTRALDFLAGS)
SOURCES=*.go imagebuildah/*.go bind/*.go chroot/*.go cmd/buildah/*.go docker/*.go pkg/blobcache/*.go pkg/cli/*.go pkg/parse/*.go util/*.go
+LINTFLAGS ?=
+
all: buildah imgtype docs
.PHONY: static
@@ -97,7 +101,7 @@ install.libseccomp.sudo: gopath
install.cni.sudo: gopath
rm -rf ../../containernetworking/plugins
git clone https://github.com/containernetworking/plugins ../../containernetworking/plugins
- cd ../../containernetworking/plugins && ./build.sh && mkdir -p /opt/cni/bin && sudo install -v -m755 bin/* /opt/cni/bin/
+ cd ../../containernetworking/plugins && ./build_linux.sh && sudo install -D -v -m755 -t /opt/cni/bin/ bin/*
.PHONY: install
install:
@@ -128,10 +132,10 @@ tests/testreport/testreport: tests/testreport/testreport.go
.PHONY: test-unit
test-unit: tests/testreport/testreport
- $(GO) test -v -tags "$(STOAGETAGS) $(SECURITYTAGS)" -race $(shell $(GO) list ./... | grep -v vendor | grep -v tests | grep -v cmd)
+ $(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -race $(shell $(GO) list ./... | grep -v vendor | grep -v tests | grep -v cmd)
tmp=$(shell mktemp -d) ; \
mkdir -p $$tmp/root $$tmp/runroot; \
- $(GO) test -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" ./cmd/buildah -args -root $$tmp/root -runroot $$tmp/runroot -storage-driver vfs -signature-policy $(shell pwd)/tests/policy.json -registries-conf $(shell pwd)/tests/registries.conf
+ $(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" ./cmd/buildah -args -root $$tmp/root -runroot $$tmp/runroot -storage-driver vfs -signature-policy $(shell pwd)/tests/policy.json -registries-conf $(shell pwd)/tests/registries.conf
vendor-in-container:
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.13 make vendor
@@ -145,4 +149,4 @@ vendor:
.PHONY: lint
lint: install.tools
- ./tests/tools/build/golangci-lint run
+ ./tests/tools/build/golangci-lint run $(LINTFLAGS)
diff --git a/vendor/github.com/containers/buildah/README.md b/vendor/github.com/containers/buildah/README.md
index 01e376a17..7589da51d 100644
--- a/vendor/github.com/containers/buildah/README.md
+++ b/vendor/github.com/containers/buildah/README.md
@@ -3,7 +3,9 @@
# [Buildah](https://www.youtube.com/embed/YVk5NgSiUw8) - a tool that facilitates building [Open Container Initiative (OCI)](https://www.opencontainers.org/) container images
[![Go Report Card](https://goreportcard.com/badge/github.com/containers/buildah)](https://goreportcard.com/report/github.com/containers/buildah)
-[![Travis](https://travis-ci.org/containers/buildah.svg?branch=master)](https://travis-ci.org/containers/buildah)
+
+[![Bors enabled](https://bors.tech/images/badge_small.svg)](https://app.bors.tech/repositories/22803)
+
The Buildah package provides a command line tool that can be used to
* create a working container, either from scratch or using an image as a starting point
diff --git a/vendor/github.com/containers/buildah/bors.toml b/vendor/github.com/containers/buildah/bors.toml
new file mode 100644
index 000000000..df68695e8
--- /dev/null
+++ b/vendor/github.com/containers/buildah/bors.toml
@@ -0,0 +1,44 @@
+# Bors-ng is a service which provides a merge and review bot for github PRs.
+# When approved for merging (`bors r+`) or test merging (`bors try`), all
+# pending PRs at the time will be merged together in one of two special
+# branches. Either 'staging' or 'trying'. In the case of `staging` branch,
+# when all status tests pass (see below) the serialized set of merges will become
+# the new destination branch HEAD (i.e. master). This guarantees there is never
+# any conflicts with PR merge order on the destination branch(es).
+#
+# Note: The branches 'staging.tmp' and 'trying.tmp' must always be ignored
+# by _all_ CI systems. They are by bors temporarily, and may go away at
+# unpredictable times.
+#
+# Format Ref: https://bors.tech/documentation/#configuration-borstoml
+#
+# status
+# ------------------
+# Selects which tests are required for merging, matching against values
+# from BOTH the older github 'status API' (ref: https://developer.github.com/v3/repos/statuses
+# /#list-statuses-for-a-specific-ref) AND newer 'checks API'. Ref: https://developer.github.com/v3/checks
+# /runs/#list-check-runs-in-a-check-suite both return JSON:
+#
+# Status API: Matches against '[].context' values
+# Checks API: Matches against 'check_runs[].name' values
+#
+# Note: The wild-card character '%' is available.
+status = [
+ "cirrus-ci/success",
+]
+
+# Same as 'status' (above) but statuses that must pass on every PR
+pr_status = [
+ "cirrus-ci/success",
+]
+
+# Cirrus-CI Max Timeout is 60 * 60 * 2
+timeout_sec = 7200
+
+# List of strings: PR Labels that must NOT be present
+block_labels = []
+
+# The number of required GitHub code reviews set 'Approve'
+# before 'bors r+' will allow merging. Does not require
+# the reviewer being in the 'Reviewers' list for the PR.
+required_approvals = 0
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index b359feaf8..2ece11acd 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -8,10 +8,10 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"time"
"github.com/containers/buildah/docker"
- "github.com/containers/buildah/util"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/ioutils"
@@ -27,7 +27,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.13.1"
+ Version = "1.15.0-dev"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
@@ -180,13 +180,8 @@ type Builder struct {
CNIConfigDir string
// ID mapping options to use when running processes in the container with non-host user namespaces.
IDMappingOptions IDMappingOptions
- // AddCapabilities is a list of capabilities to add to the default set when running
- // commands in the container.
- AddCapabilities []string
- // DropCapabilities is a list of capabilities to remove from the default set,
- // after processing the AddCapabilities set, when running commands in the container.
- // If a capability appears in both lists, it will be dropped.
- DropCapabilities []string
+ // Capabilities is a list of capabilities to use when running commands in the container.
+ Capabilities []string
// PrependedEmptyLayers are history entries that we'll add to a
// committed image, after any history items that we inherit from a base
// image, but before the history item for the layer that we're
@@ -229,13 +224,11 @@ type BuilderInfo struct {
DefaultMountsFilePath string
Isolation string
NamespaceOptions NamespaceOptions
+ Capabilities []string
ConfigureNetwork string
CNIPluginPath string
CNIConfigDir string
IDMappingOptions IDMappingOptions
- DefaultCapabilities []string
- AddCapabilities []string
- DropCapabilities []string
History []v1.History
Devices []configs.Device
}
@@ -255,6 +248,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
EmptyLayer: false,
})
history = append(history, copyHistory(b.AppendedEmptyLayers)...)
+ sort.Strings(b.Capabilities)
return BuilderInfo{
Type: b.Type,
FromImage: b.FromImage,
@@ -278,9 +272,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
CNIPluginPath: b.CNIPluginPath,
CNIConfigDir: b.CNIConfigDir,
IDMappingOptions: b.IDMappingOptions,
- DefaultCapabilities: append([]string{}, util.DefaultCapabilities...),
- AddCapabilities: append([]string{}, b.AddCapabilities...),
- DropCapabilities: append([]string{}, b.DropCapabilities...),
+ Capabilities: b.Capabilities,
History: history,
Devices: b.Devices,
}
@@ -406,19 +398,21 @@ type BuilderOptions struct {
CNIConfigDir string
// ID mapping options to use if we're setting up our own user namespace.
IDMappingOptions *IDMappingOptions
- // AddCapabilities is a list of capabilities to add to the default set when
+ // Capabilities is a list of capabilities to use when
// running commands in the container.
- AddCapabilities []string
- // DropCapabilities is a list of capabilities to remove from the default set,
- // after processing the AddCapabilities set, when running commands in the
- // container. If a capability appears in both lists, it will be dropped.
- DropCapabilities []string
-
+ Capabilities []string
CommonBuildOpts *CommonBuildOptions
// Format for the container image
Format string
// Devices are the additional devices to add to the containers
Devices []configs.Device
+ //DefaultEnv for containers
+ DefaultEnv []string
+ // MaxPullRetries is the maximum number of attempts we'll make to pull
+ // any one image from the external registry if the first attempt fails.
+ MaxPullRetries int
+ // PullRetryDelay is how long to wait before retrying a pull attempt.
+ PullRetryDelay time.Duration
}
// ImportOptions are used to initialize a Builder from an existing container
diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt
index 3f48ec4fe..8ca371869 100644
--- a/vendor/github.com/containers/buildah/changelog.txt
+++ b/vendor/github.com/containers/buildah/changelog.txt
@@ -1,3 +1,37 @@
+- Changelog for v1.14.0 (2020-02-05)
+ * bump github.com/mtrmac/gpgme
+ * Update containers/common to v0.1.4
+ * manifest push: add --format option
+ * Bump github.com/onsi/gomega from 1.8.1 to 1.9.0
+ * vendor github.com/containers/image/v5@v5.2.0
+ * info test: deal with random key order
+ * Bump back to v1.14.0-dev
+
+- Changelog for v1.13.2 (2020-01-29)
+ * sign.bats: set GPG_TTY=/dev/null
+ * Fix parse_unsupported.go
+ * getDateAndDigestAndSize(): use manifest.Digest
+ * Bump github.com/opencontainers/selinux from 1.3.0 to 1.3.1
+ * Bump github.com/containers/common from 0.1.0 to 0.1.2
+ * Touch up os/arch doc
+ * chroot: handle slightly broken seccomp defaults
+ * buildahimage: specify fuse-overlayfs mount options
+ * Bump github.com/mattn/go-shellwords from 1.0.7 to 1.0.9
+ * copy.bats: make sure we detect failures due to missing source
+ * parse: don't complain about not being able to rename something to itself
+ * Makefile: use a $(GO_TEST) macro, fix a typo
+ * manifests: unit test fix
+ * Fix build for 32bit platforms
+ * Allow users to set OS and architecture on bud
+ * Fix COPY in containerfile with envvar
+ * Bump c/storage to v1.15.7
+ * add --sign-by to bud/commit/push, --remove-signatures for pull/push
+ * Remove cut/paste error in CHANGELOG.md
+ * Update vendor of containers/common to v0.1.0
+ * update install instructions for Debian, Raspbian and Ubuntu
+ * Add support for containers.conf
+ * Bump back to v1.14.0-dev
+
- Changelog for v1.13.1 (2020-01-14)
* Bump github.com/containers/common from 0.0.5 to 0.0.7
* Bump github.com/onsi/ginkgo from 1.10.3 to 1.11.0
@@ -20,23 +54,6 @@
* discard outputs coming from onbuild command on buildah-from --quiet
* make --format columnizing consistent with buildah images
* Bump to v1.14.0-dev
- * Bump to v1.13.0
- * Bump to c/storage v1.15.5
- * Update container/storage to v1.15.4
- * Fix option handling for volumes in build
- * Rework overlay pkg for use with libpod
- * Fix buildahimage builds for buildah
- * Add support for FIPS-Mode backends
- * Set the TMPDIR for pulling/pushing image to $TMPDIR
- * WIP: safer test for pull --all-tags
- * BATS major cleanup: blobcache.bats: refactor
- * BATS major cleanup: part 4: manual stuff
- * BATS major cleanup, step 3: yet more run_buildah
- * BATS major cleanup, part 2: use more run_buildah
- * BATS major cleanup, part 1: log-level
- * Bump github.com/containers/image/v5 from 5.0.0 to 5.1.0
- * Bump github.com/containers/common from 0.0.3 to 0.0.5
- * Bump to v1.13.0-dev
- Changelog for v1.13.0 (2019-12-27)
* Bump to c/storage v1.15.5
diff --git a/vendor/github.com/containers/buildah/chroot/seccomp.go b/vendor/github.com/containers/buildah/chroot/seccomp.go
index f2c55017f..12a9b0032 100644
--- a/vendor/github.com/containers/buildah/chroot/seccomp.go
+++ b/vendor/github.com/containers/buildah/chroot/seccomp.go
@@ -3,7 +3,7 @@
package chroot
import (
- "github.com/opencontainers/runtime-spec/specs-go"
+ specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
libseccomp "github.com/seccomp/libseccomp-golang"
"github.com/sirupsen/logrus"
@@ -118,15 +118,32 @@ func setSeccomp(spec *specs.Spec) error {
continue
}
var conditions []libseccomp.ScmpCondition
+ opsAreAllEquality := true
for _, arg := range rule.Args {
condition, err := libseccomp.MakeCondition(arg.Index, mapOp(arg.Op), arg.Value, arg.ValueTwo)
if err != nil {
return errors.Wrapf(err, "error building a seccomp condition %d:%v:%d:%d", arg.Index, arg.Op, arg.Value, arg.ValueTwo)
}
+ if arg.Op != specs.OpEqualTo {
+ opsAreAllEquality = false
+ }
conditions = append(conditions, condition)
}
if err = filter.AddRuleConditional(scnum, mapAction(rule.Action), conditions); err != nil {
- return errors.Wrapf(err, "error adding a conditional rule (%q:%q) to seccomp filter", scnames[scnum], rule.Action)
+ // Okay, if the rules specify multiple equality
+ // checks, assume someone thought that they
+ // were OR'd, when in fact they're ordinarily
+ // supposed to be AND'd. Break them up into
+ // different rules to get that OR effect.
+ if len(rule.Args) > 1 && opsAreAllEquality && err.Error() == "two checks on same syscall argument" {
+ for i := range conditions {
+ if err = filter.AddRuleConditional(scnum, mapAction(rule.Action), conditions[i:i+1]); err != nil {
+ return errors.Wrapf(err, "error adding a conditional rule (%q:%q[%d]) to seccomp filter", scnames[scnum], rule.Action, i)
+ }
+ }
+ } else {
+ return errors.Wrapf(err, "error adding a conditional rule (%q:%q) to seccomp filter", scnames[scnum], rule.Action)
+ }
}
}
}
diff --git a/vendor/github.com/containers/buildah/commit.go b/vendor/github.com/containers/buildah/commit.go
index 24642f4dc..d25ba110a 100644
--- a/vendor/github.com/containers/buildah/commit.go
+++ b/vendor/github.com/containers/buildah/commit.go
@@ -12,7 +12,6 @@ import (
"github.com/containers/buildah/pkg/blobcache"
"github.com/containers/buildah/util"
- cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
@@ -81,6 +80,14 @@ type CommitOptions struct {
// OmitTimestamp forces epoch 0 as created timestamp to allow for
// deterministic, content-addressable builds.
OmitTimestamp bool
+ // SignBy is the fingerprint of a GPG key to use for signing the image.
+ SignBy string
+ // MaxRetries is the maximum number of attempts we'll make to commit
+ // the image to an external registry if the first attempt fails.
+ MaxRetries int
+ // RetryDelay is how long to wait before retrying a commit attempt to a
+ // registry.
+ RetryDelay time.Duration
}
// PushOptions can be used to alter how an image is copied somewhere.
@@ -115,6 +122,16 @@ type PushOptions struct {
// the user will be displayed, this is best used for logging.
// The default is false.
Quiet bool
+ // SignBy is the fingerprint of a GPG key to use for signing the image.
+ SignBy string
+ // RemoveSignatures causes any existing signatures for the image to be
+ // discarded for the pushed copy.
+ RemoveSignatures bool
+ // MaxRetries is the maximum number of attempts we'll make to push any
+ // one image to the external registry if the first attempt fails.
+ MaxRetries int
+ // RetryDelay is how long to wait before retrying a push attempt.
+ RetryDelay time.Duration
}
var (
@@ -293,8 +310,16 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
case archive.Gzip:
systemContext.DirForceCompress = true
}
+
+ if systemContext.ArchitectureChoice != b.Architecture() {
+ systemContext.ArchitectureChoice = b.Architecture()
+ }
+ if systemContext.OSChoice != b.OS() {
+ systemContext.OSChoice = b.OS()
+ }
+
var manifestBytes []byte
- if manifestBytes, err = cp.Image(ctx, policyContext, maybeCachedDest, maybeCachedSrc, getCopyOptions(b.store, options.ReportWriter, nil, systemContext, "")); err != nil {
+ if manifestBytes, err = retryCopyImage(ctx, policyContext, maybeCachedDest, maybeCachedSrc, dest, "push", getCopyOptions(b.store, options.ReportWriter, nil, systemContext, "", false, options.SignBy), options.MaxRetries, options.RetryDelay); err != nil {
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
}
// If we've got more names to attach, and we know how to do that for
@@ -426,7 +451,7 @@ func Push(ctx context.Context, image string, dest types.ImageReference, options
systemContext.DirForceCompress = true
}
var manifestBytes []byte
- if manifestBytes, err = cp.Image(ctx, policyContext, dest, maybeCachedSrc, getCopyOptions(options.Store, options.ReportWriter, nil, systemContext, options.ManifestType)); err != nil {
+ if manifestBytes, err = retryCopyImage(ctx, policyContext, dest, maybeCachedSrc, dest, "push", getCopyOptions(options.Store, options.ReportWriter, nil, systemContext, options.ManifestType, options.RemoveSignatures, options.SignBy), options.MaxRetries, options.RetryDelay); err != nil {
return nil, "", errors.Wrapf(err, "error copying layers and metadata from %q to %q", transports.ImageName(maybeCachedSrc), transports.ImageName(dest))
}
if options.ReportWriter != nil {
diff --git a/vendor/github.com/containers/buildah/common.go b/vendor/github.com/containers/buildah/common.go
index 35a7c6538..22bbb1efd 100644
--- a/vendor/github.com/containers/buildah/common.go
+++ b/vendor/github.com/containers/buildah/common.go
@@ -1,14 +1,26 @@
package buildah
import (
+ "context"
"io"
+ "net"
+ "net/url"
"os"
"path/filepath"
+ "syscall"
+ "time"
"github.com/containers/common/pkg/unshare"
cp "github.com/containers/image/v5/copy"
+ "github.com/containers/image/v5/docker"
+ "github.com/containers/image/v5/signature"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
+ "github.com/docker/distribution/registry/api/errcode"
+ errcodev2 "github.com/docker/distribution/registry/api/v2"
+ multierror "github.com/hashicorp/go-multierror"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
const (
@@ -18,7 +30,7 @@ const (
DOCKER = "docker"
)
-func getCopyOptions(store storage.Store, reportWriter io.Writer, sourceSystemContext *types.SystemContext, destinationSystemContext *types.SystemContext, manifestType string) *cp.Options {
+func getCopyOptions(store storage.Store, reportWriter io.Writer, sourceSystemContext *types.SystemContext, destinationSystemContext *types.SystemContext, manifestType string, removeSignatures bool, addSigner string) *cp.Options {
sourceCtx := getSystemContext(store, nil, "")
if sourceSystemContext != nil {
*sourceCtx = *sourceSystemContext
@@ -33,6 +45,8 @@ func getCopyOptions(store storage.Store, reportWriter io.Writer, sourceSystemCon
SourceCtx: sourceCtx,
DestinationCtx: destinationCtx,
ForceManifestMIMEType: manifestType,
+ RemoveSignatures: removeSignatures,
+ SignBy: addSigner,
}
}
@@ -57,3 +71,65 @@ func getSystemContext(store storage.Store, defaults *types.SystemContext, signat
}
return sc
}
+
+func isRetryable(err error) bool {
+ err = errors.Cause(err)
+ type unwrapper interface {
+ Unwrap() error
+ }
+ if unwrapper, ok := err.(unwrapper); ok {
+ err = unwrapper.Unwrap()
+ return isRetryable(err)
+ }
+ if registryError, ok := err.(errcode.Error); ok {
+ switch registryError.Code {
+ case errcode.ErrorCodeUnauthorized, errcodev2.ErrorCodeNameUnknown, errcodev2.ErrorCodeManifestUnknown:
+ return false
+ }
+ return true
+ }
+ if op, ok := err.(*net.OpError); ok {
+ return isRetryable(op.Err)
+ }
+ if url, ok := err.(*url.Error); ok {
+ return isRetryable(url.Err)
+ }
+ if errno, ok := err.(syscall.Errno); ok {
+ if errno == syscall.ECONNREFUSED {
+ return false
+ }
+ }
+ if errs, ok := err.(errcode.Errors); ok {
+ // if this error is a group of errors, process them all in turn
+ for i := range errs {
+ if !isRetryable(errs[i]) {
+ return false
+ }
+ }
+ }
+ if errs, ok := err.(*multierror.Error); ok {
+ // if this error is a group of errors, process them all in turn
+ for i := range errs.Errors {
+ if !isRetryable(errs.Errors[i]) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func retryCopyImage(ctx context.Context, policyContext *signature.PolicyContext, dest, src, registry types.ImageReference, action string, copyOptions *cp.Options, maxRetries int, retryDelay time.Duration) ([]byte, error) {
+ manifestBytes, err := cp.Image(ctx, policyContext, dest, src, copyOptions)
+ for retries := 0; err != nil && isRetryable(err) && registry != nil && registry.Transport().Name() == docker.Transport.Name() && retries < maxRetries; retries++ {
+ if retryDelay == 0 {
+ retryDelay = 5 * time.Second
+ }
+ logrus.Infof("Warning: %s failed, retrying in %s ... (%d/%d)", action, retryDelay, retries+1, maxRetries)
+ time.Sleep(retryDelay)
+ manifestBytes, err = cp.Image(ctx, policyContext, dest, src, copyOptions)
+ if err == nil {
+ break
+ }
+ }
+ return manifestBytes, err
+}
diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod
index b4f7d82db..0172da01b 100644
--- a/vendor/github.com/containers/buildah/go.mod
+++ b/vendor/github.com/containers/buildah/go.mod
@@ -3,46 +3,39 @@ module github.com/containers/buildah
go 1.12
require (
- github.com/blang/semver v3.5.0+incompatible // indirect
- github.com/containernetworking/cni v0.7.1
- github.com/containers/common v0.0.7
- github.com/containers/image/v5 v5.1.0
- github.com/containers/storage v1.15.5
+ github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
+ github.com/containers/common v0.4.1
+ github.com/containers/image/v5 v5.2.1
+ github.com/containers/storage v1.16.0
github.com/cyphar/filepath-securejoin v0.2.2
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.4.0
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316
github.com/etcd-io/bbolt v1.3.3
- github.com/fsouza/go-dockerclient v1.6.0
+ github.com/fsouza/go-dockerclient v1.6.3
github.com/ghodss/yaml v1.0.0
github.com/hashicorp/go-multierror v1.0.0
- github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111 // indirect
- github.com/mattn/go-shellwords v1.0.6
- github.com/morikuni/aec v1.0.0 // indirect
- github.com/onsi/ginkgo v1.11.0
- github.com/onsi/gomega v1.8.1
+ github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect
+ github.com/mattn/go-shellwords v1.0.10
+ github.com/onsi/ginkgo v1.12.0
+ github.com/onsi/gomega v1.9.0
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/runc v1.0.0-rc9
github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7
github.com/opencontainers/runtime-tools v0.9.0
- github.com/opencontainers/selinux v1.3.0
+ github.com/opencontainers/selinux v1.3.2
github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316
github.com/openshift/imagebuilder v1.1.1
- github.com/pkg/errors v0.9.0
- github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4
+ github.com/pkg/errors v0.9.1
+ github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
github.com/seccomp/libseccomp-golang v0.9.1
github.com/sirupsen/logrus v1.4.2
- github.com/spf13/cobra v0.0.5
+ github.com/spf13/cobra v0.0.6
github.com/spf13/pflag v1.0.5
- github.com/stretchr/testify v1.4.0
+ github.com/stretchr/testify v1.5.1
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
- github.com/vishvananda/netlink v1.0.0 // indirect
- github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f // indirect
- github.com/xeipuuv/gojsonschema v1.1.0 // indirect
- golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
+ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2
- golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect
- k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083 // indirect
)
diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum
index e32fb0bec..60c040165 100644
--- a/vendor/github.com/containers/buildah/go.sum
+++ b/vendor/github.com/containers/buildah/go.sum
@@ -1,13 +1,16 @@
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=
+github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
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/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 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
@@ -21,23 +24,35 @@ github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhj
github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+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/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 h1:7hqmJYuaEK3qwVjWubYiht3j93YI0WQBuysxHIfUriU=
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=
+github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
+github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
@@ -56,22 +71,53 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
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.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
+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.5 h1:Hi4+eyUZx8hXB4reLNPbdT6XT8MGMAzdlbg8V+WifkQ=
github.com/containers/common v0.0.5/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
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/common v0.0.8-0.20200106141003-a79791495fd1 h1:udiDqxQSdunVXNjBW4icHrnFLNOiTpvH6GRG+ywA4f4=
+github.com/containers/common v0.0.8-0.20200106141003-a79791495fd1/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
+github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b h1:G+DKyzrku0fC5Qa3paArNBERTwRleTg45ypY0qjo7YM=
+github.com/containers/common v0.0.8-0.20200108114752-d87ce6ce296b/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.1.0 h1:RsAxx1yeepYhXXEasNpspi/nPC8KKP1AzzOgEuvfWXk=
+github.com/containers/common v0.1.0/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.1.2 h1:EYAgJsQgH3akh6kdlN4c2t09bqRgyzpxyWmlFTf1Igc=
+github.com/containers/common v0.1.2/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.1.4 h1:6tizbvX9BJTnJ0S3pe65Vcu8gJagbm6oFBCmwUIiOE4=
+github.com/containers/common v0.1.4/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.2.0 h1:umTbAiX39/0oNxHn10ia0RyXrZCs/CnjJQlRiTdiXb8=
+github.com/containers/common v0.2.0/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.2.1 h1:sEMQm9S+Z7zaQNaSJYbJ5DeR539rk8qscH11RMYw9Fk=
+github.com/containers/common v0.2.1/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/containers/common v0.3.0 h1:9ysL/OfPcMls1Ac3jzFA4XZJVSD/JG7Dst3uQSwQtwA=
+github.com/containers/common v0.3.0/go.mod h1:AiPCv0ZcBOVshnup/X6MuaqkySZQZ3iBWfInjJFIl40=
+github.com/containers/common v0.4.0 h1:LpX2J19cZKSpn4PBtbLX/tTk3JzTtaqRWbaEoX5YGAI=
+github.com/containers/common v0.4.0/go.mod h1:AiPCv0ZcBOVshnup/X6MuaqkySZQZ3iBWfInjJFIl40=
+github.com/containers/common v0.4.1 h1:Uu7f2ZDM/5xsqOkZwIEVKSjUI3YxKjvNIY5x57kjaKo=
+github.com/containers/common v0.4.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
+github.com/containers/conmon v2.0.10+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ=
github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA=
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=
+github.com/containers/image/v5 v5.2.1 h1:rQR6QSUneWBoW1bTFpP9EJJTevQFv27YsKYQVJIzg+s=
+github.com/containers/image/v5 v5.2.1/go.mod h1:TfhmLwH+v1/HBVPIWH7diLs8XwcOkP3c7t7JFgqaUEc=
+github.com/containers/libpod v1.8.0/go.mod h1:53h7AOg4tQSX1rqKfR78/6Us/whERRzCQ20z0GiR44U=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJtUcZgK7sPglscXtxvMOnFOa6wd09VWLM=
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
+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=
@@ -93,20 +139,39 @@ github.com/containers/storage v1.15.4 h1:eiUtV9MOTnPHibO18nDRI+aDhKudY7WmAiJdyVM
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/containers/storage v1.16.0 h1:sD+s7BmiNBh61CuHN3j8PXGCwMtV9zPVJETAlshIf3w=
+github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPbNkN/xb0TfG0=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
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.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/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=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b/go.mod h1:ZOuIEOp/3MB1eCBWANnNxM3zUA3NWh76wSRCsnKAg2c=
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
+github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
+github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
+github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
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=
@@ -118,6 +183,8 @@ github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce h1:H3csZuxZESJeeEi
github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce/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=
@@ -135,12 +202,18 @@ github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316/go.mod h
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/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+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/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+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=
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/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=
github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+frvw8z04=
@@ -149,12 +222,17 @@ github.com/fsouza/go-dockerclient v1.5.0 h1:7OtayOe5HnoG+KWMHgyyPymwaodnB2IDYuVf
github.com/fsouza/go-dockerclient v1.5.0/go.mod h1:AqZZK/zFO3phxYxlTsAaeAMSdQ9mgHuhy+bjN034Qds=
github.com/fsouza/go-dockerclient v1.6.0 h1:f7j+AX94143JL1H3TiqSMkM4EcLDI0De1qD4GGn3Hig=
github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+4np9qfPbb+znGc=
+github.com/fsouza/go-dockerclient v1.6.1 h1:qBvbtwBTpOYktncvxjFMHxJHuGG19lb2fvAFqfXeh7w=
+github.com/fsouza/go-dockerclient v1.6.1/go.mod h1:g2pGMa82+SdtAicFSpxGJc1Anx//HHssXyWLwMRxaqg=
+github.com/fsouza/go-dockerclient v1.6.3 h1:VS/I3mxieZVIeaWXd57JKvSjheELafUJYtblGg75RIQ=
+github.com/fsouza/go-dockerclient v1.6.3/go.mod h1:OiSy/IhZIF+zheikZkXK7LVpGzxWchJPJKGWhBqOK4M=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
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/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=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -171,9 +249,12 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
+github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
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/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
@@ -181,6 +262,7 @@ github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5
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/groupcache v0.0.0-20190129154638-5b532d6fd5ef/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/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -189,21 +271,37 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a
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/btree v1.0.0/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/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/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
+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=
+github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
+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/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
+github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -225,13 +323,24 @@ 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=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/insomniacslk/dhcp v0.0.0-20190712084813-dc1a53400564/go.mod h1:CfMdguCK66I5DAUJgGKyNz8aB6vO5dZzkm9Xep6WGvw=
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111 h1:NAAiV9ass6VReWFjuxqrMIq12WKlSULI6Gs3PxQghLA=
github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
+github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 h1:rw3IAne6CDuVFlZbPOkA7bhxlqawFh7RJJ+CejfMaxE=
+github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
+github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
+github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
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/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/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
+github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
+github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
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=
@@ -248,6 +357,12 @@ github.com/klauspost/compress v1.9.3 h1:hkFELABwacUEgBfiguNeQydKv3M9pawBq8o24Ypw
github.com/klauspost/compress v1.9.3/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/compress v1.10.0 h1:92XGj1AcYzA6UrVdd4qIIBrT8OroryvRvdmg/IfmC7Y=
+github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
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=
@@ -270,16 +385,25 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
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/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/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
+github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/moby/vpnkit v0.3.1-0.20190720080441-7dd3dcce7d3d/go.mod h1:KyjUrL9cb6ZSNNAUwZfqRjhwwgJ3BJN+kXh0t43WTUQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -287,14 +411,24 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
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/go.mod h1:YBPKCT1PrhoFU743gPdtJNp+LmM0QlGMWME1J+FJtQI=
+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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+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 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -308,7 +442,11 @@ 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 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
@@ -317,6 +455,8 @@ 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=
@@ -325,6 +465,7 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
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=
@@ -342,6 +483,10 @@ github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4Ft
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/opencontainers/selinux v1.3.2 h1:DR4lL9SYVjgcTZKEZIncvDU06fKSc/eygjmNGOA3E1s=
+github.com/opencontainers/selinux v1.3.2/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=
@@ -350,14 +495,20 @@ github.com/openshift/imagebuilder v1.1.0 h1:oT704SkwMEzmIMU/+Uv1Wmvt+p10q3v2WuYM
github.com/openshift/imagebuilder v1.1.0/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
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/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+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/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=
@@ -366,24 +517,37 @@ github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BU
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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
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=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
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.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
+github.com/rhatdan/common v0.0.3-0.20200203010855-77d72c3e2feb h1:pABQ1OA6mO8XrdHran0oaTEvSb2aZpM+bI8+NfcjALQ=
+github.com/rhatdan/common v0.0.3-0.20200203010855-77d72c3e2feb/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/rhatdan/common v0.0.3-0.20200208104512-837f7aa36449 h1:3uEI2WT7ZUWIKbbyKjm7etLgSSMOmdiJ4cqksVnuV9A=
+github.com/rhatdan/common v0.0.3-0.20200208104512-837f7aa36449/go.mod h1:ss8uGpUsaDE4DPmaVFOjzKrlgf5eUnSAWL+d/PYGaoM=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
+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/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/saschagrunert/storage v1.12.3-0.20191015073819-a34ddea087da h1:5aEGhStFh+0r/t0kT0utSi5C6MIMHBgMHkeIu1JUvfA=
github.com/saschagrunert/storage v1.12.3-0.20191015073819-a34ddea087da/go.mod h1:imKnA8Ozb99yPWt64WPrtNOR0v0HKQZFH4oLV45N22k=
github.com/saschagrunert/storage v1.12.3-0.20191018073047-1d43d5290f84 h1:iBs6FOO2GpFpdaa3WC4XhqHI6S2LE7RTlgn8LodsXVo=
@@ -410,27 +574,39 @@ github.com/saschagrunert/storage v1.12.3-0.20191204101521-aca03d333c53 h1:CBWb8W
github.com/saschagrunert/storage v1.12.3-0.20191204101521-aca03d333c53/go.mod h1:/Lild6FqQu2HwAVjVC9d5EAls3Mqwoxx67XpnR4UgEY=
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=
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v0.0.0-20190403091019-9b3cdde74fbe/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs=
+github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
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=
@@ -438,26 +614,42 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
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=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/u-root/u-root v5.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
+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/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+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/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
+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/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=
@@ -465,18 +657,27 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
+github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66 h1:F6RPtD6im1kY4bmLByRlOLOZwsPP7mw7cxR1v2CotL0=
github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
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=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+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 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -484,6 +685,8 @@ golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5
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=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -496,11 +699,17 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+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=
@@ -509,6 +718,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+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=
@@ -520,6 +731,7 @@ golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -527,14 +739,18 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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=
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/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 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
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=
@@ -543,13 +759,18 @@ golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7w
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=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -563,26 +784,35 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 h1:9VBRTdmgQxbs6HE0sUnMrSWNePppAJU07NYvX5dIB04=
+google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
+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=
@@ -591,46 +821,65 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
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=
+gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
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.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
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.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/client-go v0.0.0-20170217214107-bcde30fb7eae h1:B3EgNIqpnsZRu7Tms/u6i23BcsxtEKAqXrHt45OqNuw=
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=
k8s.io/code-generator v0.17.0/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
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 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
k8s.io/klog v0.3.1/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=
+k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index 484eb4efd..e113871c7 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -11,13 +11,14 @@ import (
"os/exec"
"path/filepath"
"strings"
+ "time"
"github.com/containers/buildah"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
- "github.com/opencontainers/runc/libcontainer/configs"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/openshift/imagebuilder"
"github.com/pkg/errors"
@@ -66,7 +67,7 @@ type BuildOptions struct {
// RuntimeArgs adds global arguments for the runtime.
RuntimeArgs []string
// TransientMounts is a list of mounts that won't be kept in the image.
- TransientMounts []Mount
+ TransientMounts []string
// Compression specifies the type of compression which is applied to
// layer blobs. The default is to not use compression, but
// archive.Gzip is recommended.
@@ -156,10 +157,21 @@ type BuildOptions struct {
ForceRmIntermediateCtrs bool
// BlobDirectory is a directory which we'll use for caching layer blobs.
BlobDirectory string
- // Target the targeted FROM in the Dockerfile to build
+ // Target the targeted FROM in the Dockerfile to build.
Target string
- // Devices are the additional devices to add to the containers
- Devices []configs.Device
+ // Devices are the additional devices to add to the containers.
+ Devices []string
+ // SignBy is the fingerprint of a GPG key to use for signing images.
+ SignBy string
+ // Architecture specifies the target architecture of the image to be built.
+ Architecture string
+ // OS is the specifies the operating system of the image to be built.
+ OS string
+ // MaxPullPushRetries is the maximum number of attempts we'll make to pull or push any one
+ // image from or to an external registry if the first attempt fails.
+ MaxPullPushRetries int
+ // PullPushRetryDelay is how long to wait before retrying a pull or push attempt.
+ PullPushRetryDelay time.Duration
}
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be
@@ -250,6 +262,11 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
return "", nil, errors.Wrapf(err, "error creating build executor")
}
b := imagebuilder.NewBuilder(options.Args)
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return "", nil, errors.Wrapf(err, "failed to get container config")
+ }
+ b.Env = append(defaultContainerConfig.GetDefaultEnv(), b.Env...)
stages, err := imagebuilder.NewStages(mainNode, b)
if err != nil {
return "", nil, errors.Wrap(err, "error reading multiple stages")
diff --git a/vendor/github.com/containers/buildah/imagebuildah/executor.go b/vendor/github.com/containers/buildah/imagebuildah/executor.go
index 35fc3d63d..846900656 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/executor.go
@@ -9,9 +9,12 @@ import (
"sort"
"strconv"
"strings"
+ "time"
"github.com/containers/buildah"
+ "github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
is "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/transports"
@@ -91,17 +94,46 @@ type Executor struct {
excludes []string
unusedArgs map[string]struct{}
buildArgs map[string]string
- addCapabilities []string
- dropCapabilities []string
+ capabilities []string
devices []configs.Device
+ signBy string
+ architecture string
+ os string
+ maxPullPushRetries int
+ retryPullPushDelay time.Duration
}
// NewExecutor creates a new instance of the imagebuilder.Executor interface.
func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Node) (*Executor, error) {
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to get container config")
+ }
+
excludes, err := imagebuilder.ParseDockerignore(options.ContextDirectory)
if err != nil {
return nil, err
}
+ capabilities := defaultContainerConfig.Capabilities("", options.AddCapabilities, options.DropCapabilities)
+
+ devices := []configs.Device{}
+ for _, device := range append(defaultContainerConfig.Containers.Devices, options.Devices...) {
+ dev, err := parse.DeviceFromPath(device)
+ if err != nil {
+ return nil, err
+ }
+ devices = append(dev, devices...)
+ }
+
+ transientMounts := []Mount{}
+ for _, volume := range append(defaultContainerConfig.Containers.Volumes, options.TransientMounts...) {
+ mount, err := parse.Volume(volume)
+ if err != nil {
+ return nil, err
+ }
+
+ transientMounts = append([]Mount{Mount(mount)}, transientMounts...)
+ }
exec := Executor{
store: store,
@@ -113,7 +145,7 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
quiet: options.Quiet,
runtime: options.Runtime,
runtimeArgs: options.RuntimeArgs,
- transientMounts: options.TransientMounts,
+ transientMounts: transientMounts,
compression: options.Compression,
output: options.Output,
outputFormat: options.OutputFormat,
@@ -147,10 +179,14 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
rootfsMap: make(map[string]bool),
blobDirectory: options.BlobDirectory,
unusedArgs: make(map[string]struct{}),
- buildArgs: options.Args,
- addCapabilities: options.AddCapabilities,
- dropCapabilities: options.DropCapabilities,
- devices: options.Devices,
+ buildArgs: copyStringStringMap(options.Args),
+ capabilities: capabilities,
+ devices: devices,
+ signBy: options.SignBy,
+ architecture: options.Architecture,
+ os: options.OS,
+ maxPullPushRetries: options.MaxPullPushRetries,
+ retryPullPushDelay: options.PullPushRetryDelay,
}
if exec.err == nil {
exec.err = os.Stderr
@@ -527,7 +563,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
if err := cleanup(); err != nil {
return "", nil, err
}
-
+ logrus.Debugf("printing final image id %q", imageID)
if b.iidfile != "" {
if err = ioutil.WriteFile(b.iidfile, []byte(imageID), 0644); err != nil {
return imageID, ref, errors.Wrapf(err, "failed to write image ID to file %q", b.iidfile)
@@ -537,7 +573,6 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
return imageID, ref, errors.Wrapf(err, "failed to write image ID to stdout")
}
}
-
return imageID, ref, nil
}
diff --git a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
index b54caf3ef..6216dac97 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/buildah"
buildahdocker "github.com/containers/buildah/docker"
+ "github.com/containers/buildah/pkg/chrootuser"
"github.com/containers/buildah/util"
cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker/reference"
@@ -253,7 +254,7 @@ func (s *StageExecutor) volumeCacheRestore() error {
// don't care about the details of where in the filesystem the content actually
// goes, because we're not actually going to add it here, so this is less
// involved than Copy().
-func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []string) (string, error) {
+func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []string, envValues []string) (string, error) {
// No instruction: done.
if node == nil {
return "", nil
@@ -298,10 +299,11 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
}
}
+ varValues := append(argValues, envValues...)
for _, src := range srcs {
// If src has an argument within it, resolve it to its
// value. Otherwise just return the value found.
- name, err := imagebuilder.ProcessWord(src, argValues)
+ name, err := imagebuilder.ProcessWord(src, varValues)
if err != nil {
return "", errors.Wrapf(err, "unable to resolve source %q", src)
}
@@ -315,8 +317,12 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
} else {
// Source is not a URL, so it's a location relative to
// the all-content-comes-from-below-this-directory
- // directory.
+ // directory. Also raise an error if the src escapes
+ // the context directory.
contextSrc, err := securejoin.SecureJoin(contextDir, src)
+ if err == nil && strings.HasPrefix(src, "../") {
+ err = errors.New("escaping context directory error")
+ }
if err != nil {
return "", errors.Wrapf(err, "forbidden path for %q, it is outside of the build context %q", src, contextDir)
}
@@ -345,7 +351,7 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
// If destination.Value has an argument within it, resolve it to its
// value. Otherwise just return the value found.
- destValue, destErr := imagebuilder.ProcessWord(destination.Value, argValues)
+ destValue, destErr := imagebuilder.ProcessWord(destination.Value, varValues)
if destErr != nil {
return "", errors.Wrapf(destErr, "unable to resolve destination %q", destination.Value)
}
@@ -434,8 +440,12 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
// Treat the source, which is not a URL, as a
// location relative to the
// all-content-comes-from-below-this-directory
- // directory.
+ // directory. Also raise an error if the src
+ // escapes the context directory.
srcSecure, err := securejoin.SecureJoin(contextDir, src)
+ if err == nil && strings.HasPrefix(src, "../") {
+ err = errors.New("escaping context directory error")
+ }
if err != nil {
return errors.Wrapf(err, "forbidden path for %q, it is outside of the build context %q", src, contextDir)
}
@@ -452,6 +462,11 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
Excludes: copyExcludes,
IDMappingOptions: idMappingOptions,
}
+ // If we've a tar file, it will create a directory using the name of the tar
+ // file if we don't blank it out.
+ if strings.HasSuffix(srcName, ".tar") || strings.HasSuffix(srcName, ".gz") {
+ srcName = ""
+ }
if err := s.builder.Add(filepath.Join(copy.Dest, srcName), copy.Download, options, srcSecure); err != nil {
return err
}
@@ -605,9 +620,10 @@ func (s *StageExecutor) prepare(ctx context.Context, stage imagebuilder.Stage, f
CommonBuildOpts: s.executor.commonBuildOptions,
DefaultMountsFilePath: s.executor.defaultMountsFilePath,
Format: s.executor.outputFormat,
- AddCapabilities: s.executor.addCapabilities,
- DropCapabilities: s.executor.dropCapabilities,
+ Capabilities: s.executor.capabilities,
Devices: s.executor.devices,
+ MaxPullRetries: s.executor.maxPullPushRetries,
+ PullRetryDelay: s.executor.retryPullPushDelay,
}
// Check and see if the image is a pseudonym for the end result of a
@@ -771,8 +787,12 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
}
logImageID := func(imgID string) {
+ if len(imgID) > 11 {
+ imgID = imgID[0:11]
+ }
if s.executor.iidfile == "" {
- fmt.Fprintf(s.executor.out, "%s\n", imgID)
+
+ fmt.Fprintf(s.executor.out, "--> %s\n", imgID)
}
}
@@ -869,7 +889,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
}
// In case we added content, retrieve its digest.
- addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
+ addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -918,7 +938,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// cached images so far, look for one that matches what we
// expect to produce for this instruction.
if checkForLayers && !(s.executor.squash && lastInstruction && lastStage) {
- addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
+ addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -976,7 +996,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
}
// In case we added content, retrieve its digest.
- addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
+ addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -1013,7 +1033,6 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
}
}
-
return imgID, ref, nil
}
@@ -1132,6 +1151,8 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
}
s.builder.SetHostname(config.Hostname)
s.builder.SetDomainname(config.Domainname)
+ s.builder.SetArchitecture(s.executor.architecture)
+ s.builder.SetOS(s.executor.os)
s.builder.SetUser(config.User)
s.builder.ClearPorts()
for p := range config.ExposedPorts {
@@ -1204,6 +1225,9 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
Squash: s.executor.squash,
EmptyLayer: emptyLayer,
BlobDirectory: s.executor.blobDirectory,
+ SignBy: s.executor.signBy,
+ MaxRetries: s.executor.maxPullPushRetries,
+ RetryDelay: s.executor.retryPullPushDelay,
}
imgID, _, manifestDigest, err := s.builder.Commit(ctx, imageRef, options)
if err != nil {
@@ -1225,9 +1249,22 @@ func (s *StageExecutor) EnsureContainerPath(path string) error {
if err != nil {
return errors.Wrapf(err, "error ensuring container path %q", path)
}
- _, err = os.Lstat(targetPath)
+
+ _, err = os.Stat(targetPath)
if err != nil && os.IsNotExist(err) {
err = os.MkdirAll(targetPath, 0755)
+ if err != nil {
+ return errors.Wrapf(err, "error creating directory path %q", targetPath)
+ }
+ // get the uid and gid so that we can set the correct permissions on the
+ // working directory
+ uid, gid, _, err := chrootuser.GetUser(s.mountPoint, s.builder.User())
+ if err != nil {
+ return errors.Wrapf(err, "error getting uid and gid for user %q", s.builder.User())
+ }
+ if err = os.Chown(targetPath, int(uid), int(gid)); err != nil {
+ return errors.Wrapf(err, "error setting ownership on %q", targetPath)
+ }
}
if err != nil {
return errors.Wrapf(err, "error ensuring container path %q", path)
diff --git a/vendor/github.com/containers/buildah/imagebuildah/util.go b/vendor/github.com/containers/buildah/imagebuildah/util.go
index 520b92e3f..29ea60970 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/util.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/util.go
@@ -165,3 +165,11 @@ func convertMounts(mounts []Mount) []specs.Mount {
}
return specmounts
}
+
+func copyStringStringMap(m map[string]string) map[string]string {
+ n := map[string]string{}
+ for k, v := range m {
+ n[k] = v
+ }
+ return n
+}
diff --git a/vendor/github.com/containers/buildah/info.go b/vendor/github.com/containers/buildah/info.go
index 1e6d6b746..a40af08ed 100644
--- a/vendor/github.com/containers/buildah/info.go
+++ b/vendor/github.com/containers/buildah/info.go
@@ -12,7 +12,6 @@ import (
"time"
"github.com/containers/buildah/util"
- "github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/unshare"
"github.com/containers/storage"
"github.com/containers/storage/pkg/system"
@@ -48,7 +47,7 @@ func hostInfo() map[string]interface{} {
info["cpus"] = runtime.NumCPU()
info["rootless"] = unshare.IsRootless()
- unified, err := cgroups.IsCgroup2UnifiedMode()
+ unified, err := util.IsCgroup2UnifiedMode()
if err != nil {
logrus.Error(err, "err reading cgroups mode")
}
diff --git a/vendor/github.com/containers/buildah/install.md b/vendor/github.com/containers/buildah/install.md
index 91522f64f..b5e1abda0 100644
--- a/vendor/github.com/containers/buildah/install.md
+++ b/vendor/github.com/containers/buildah/install.md
@@ -4,12 +4,87 @@
## Installing packaged versions of buildah
+#### [Amazon Linux 2](https://aws.amazon.com/amazon-linux-2/)
+
+The [Kubic project](https://build.opensuse.org/project/show/devel:kubic:libcontainers:stable)
+provides updated packages for CentOS 7 which can be used unmodified on Amazon Linux 2.
+
+```bash
+cd /etc/yum.repos.d/
+sudo wget https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_7/devel:kubic:libcontainers:stable.repo
+sudo yum -y install buildah
+```
+
### [Arch Linux](https://www.archlinux.org)
```bash
sudo pacman -S buildah
```
+#### [CentOS](https://www.centos.org)
+
+Buildah is available in the default Extras repos for CentOS 7 and in
+the AppStream repo for CentOS 8 and Stream, however the available version often
+lags the upstream release.
+
+```bash
+sudo yum -y install buildah
+```
+
+The [Kubic project](https://build.opensuse.org/project/show/devel:kubic:libcontainers:stable)
+provides updated packages for CentOS 7, 8 and Stream.
+
+```bash
+# CentOS 7
+cd /etc/yum.repos.d/
+sudo wget https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_7/devel:kubic:libcontainers:stable.repo
+sudo yum -y install buildah
+
+# CentOS 8
+sudo dnf -y module disable container-tools
+sudo dnf -y install 'dnf-command(copr)'
+sudo dnf -y copr enable rhcontainerbot/container-selinux
+cd /etc/yum.repos.d
+sudo wget https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_8/devel:kubic:libcontainers:stable.repo
+sudo dnf -y install buildah
+
+# CentOS Stream
+sudo dnf -y module disable container-tools
+sudo dnf -y install 'dnf-command(copr)'
+sudo dnf -y copr enable rhcontainerbot/container-selinux
+cd /etc/yum.repos.d
+sudo wget https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_8_Stream/devel:kubic:libcontainers:stable.repo
+sudo dnf -y install buildah
+```
+
+
+#### [Debian](https://debian.org)
+
+The buildah package is [being worked on](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=928083)
+for inclusion in the default Debian repos.
+
+Alternatively, the [Kubic project](https://build.opensuse.org/project/show/devel:kubic:libcontainers:stable)
+provides packages for Debian 10, testing and unstable.
+
+```bash
+# Debian Unstable/Sid
+echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
+wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Unstable/Release.key -O Release.key
+
+# Debian Testing
+echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Testing/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
+wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Testing/Release.key -O Release.key
+
+# Debian 10
+echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
+wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_10/Release.key -O Release.key
+
+sudo apt-key add - < Release.key
+sudo apt-get update -qq
+sudo apt-get -qq -y install buildah
+```
+
+
### [Fedora](https://www.fedoraproject.org), [CentOS](https://www.centos.org)
```bash
@@ -26,7 +101,7 @@ Not Available. Must be installed via package layering.
rpm-ostree install buildah
-Note: `[podman](https://podman.io) build` is available by default.
+Note: [`podman`](https://podman.io) build is available by default.
### [Gentoo](https://www.gentoo.org)
@@ -53,6 +128,19 @@ sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
sudo yum -y install buildah
```
+#### [Raspbian](https://raspbian.org)
+
+The Kubic project provides packages for Raspbian 10.
+
+```bash
+# Raspbian 10
+echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
+wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Raspbian_10/Release.key -O Release.key
+sudo apt-key add - < Release.key
+sudo apt-get update -qq
+sudo apt-get -qq -y install buildah
+```
+
### [RHEL8 Beta](https://www.redhat.com/en/blog/powering-its-future-while-preserving-present-introducing-red-hat-enterprise-linux-8-beta?intcmp=701f2000001Cz6OAAS)
```bash
@@ -62,10 +150,13 @@ sudo yum module install -y buildah
### [Ubuntu](https://www.ubuntu.com)
+The Kubic project provides packages for Ubuntu 18.04, 19.04 and 19.10 (it should also work with direct derivatives like Pop!\_OS).
+
```bash
-sudo apt-get update -qq
-sudo apt-get install -qq -y software-properties-common
-sudo add-apt-repository -y ppa:projectatomic/ppa
+. /etc/os-release
+sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${ID^}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
+wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${ID^}_${VERSION_ID}/Release.key -O Release.key
+sudo apt-key add - < Release.key
sudo apt-get update -qq
sudo apt-get -qq -y install buildah
```
@@ -107,9 +198,9 @@ named `containernetworking-cni`). If not, they will need to be installed,
for example using:
```
git clone https://github.com/containernetworking/plugins
- ( cd ./plugins; ./build.sh )
- mkdir -p /opt/cni/bin
- install -v ./plugins/bin/* /opt/cni/bin
+ ( cd ./plugins; ./build_linux.sh )
+ sudo mkdir -p /opt/cni/bin
+ sudo install -v ./plugins/bin/* /opt/cni/bin
```
The CNI library needs to be configured so that it will know which plugins to
@@ -233,13 +324,13 @@ The build steps for Buildah on SUSE / openSUSE are the same as for Fedora, above
In Ubuntu zesty and xenial, you can use these commands:
```
- apt-get -y install software-properties-common
- add-apt-repository -y ppa:alexlarsson/flatpak
- add-apt-repository -y ppa:gophers/archive
- apt-add-repository -y ppa:projectatomic/ppa
- apt-get -y -qq update
- apt-get -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
- apt-get -y install golang-1.12
+ sudo apt-get -y install software-properties-common
+ sudo add-apt-repository -y ppa:alexlarsson/flatpak
+ sudo add-apt-repository -y ppa:gophers/archive
+ sudo apt-add-repository -y ppa:projectatomic/ppa
+ sudo apt-get -y -qq update
+ sudo apt-get -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
+ sudo apt-get -y install golang-1.12
```
Then to install Buildah on Ubuntu follow the steps in this example:
@@ -249,7 +340,7 @@ Then to install Buildah on Ubuntu follow the steps in this example:
export GOPATH=`pwd`
git clone https://github.com/containers/buildah ./src/github.com/containers/buildah
cd ./src/github.com/containers/buildah
- PATH=/usr/lib/go-1.10/bin:$PATH make runc all SECURITYTAGS="apparmor seccomp"
+ PATH=/usr/lib/go-1.12/bin:$PATH make runc all SECURITYTAGS="apparmor seccomp"
sudo make install install.runc
buildah --help
```
@@ -260,11 +351,11 @@ To install the required dependencies, you can use those commands, tested under D
```
gpg --recv-keys 0x018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D
-gpg --export 0x018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D >> /usr/share/keyrings/projectatomic-ppa.gpg
-echo 'deb [signed-by=/usr/share/keyrings/projectatomic-ppa.gpg] http://ppa.launchpad.net/projectatomic/ppa/ubuntu zesty main' > /etc/apt/sources.list.d/projectatomic-ppa.list
-apt update
-apt -y install -t stretch-backports golang
-apt -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
+sudo gpg --export 0x018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D >> /usr/share/keyrings/projectatomic-ppa.gpg
+sudo echo 'deb [signed-by=/usr/share/keyrings/projectatomic-ppa.gpg] http://ppa.launchpad.net/projectatomic/ppa/ubuntu zesty main' > /etc/apt/sources.list.d/projectatomic-ppa.list
+sudo apt update
+sudo apt -y install -t stretch-backports golang
+sudo apt -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
```
The build steps on Debian are otherwise the same as Ubuntu, above.
diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go
index da6b357bf..a6b6899e0 100644
--- a/vendor/github.com/containers/buildah/new.go
+++ b/vendor/github.com/containers/buildah/new.go
@@ -34,6 +34,8 @@ func pullAndFindImage(ctx context.Context, store storage.Store, srcRef types.Ima
Store: store,
SystemContext: options.SystemContext,
BlobDirectory: options.BlobDirectory,
+ MaxRetries: options.MaxPullRetries,
+ RetryDelay: options.PullRetryDelay,
}
ref, err := pullImage(ctx, store, srcRef, pullOptions, sc)
if err != nil {
@@ -398,14 +400,13 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
UIDMap: uidmap,
GIDMap: gidmap,
},
- AddCapabilities: copyStringSlice(options.AddCapabilities),
- DropCapabilities: copyStringSlice(options.DropCapabilities),
- CommonBuildOpts: options.CommonBuildOpts,
- TopLayer: topLayer,
- Args: options.Args,
- Format: options.Format,
- TempVolumes: map[string]bool{},
- Devices: options.Devices,
+ Capabilities: copyStringSlice(options.Capabilities),
+ CommonBuildOpts: options.CommonBuildOpts,
+ TopLayer: topLayer,
+ Args: options.Args,
+ Format: options.Format,
+ TempVolumes: map[string]bool{},
+ Devices: options.Devices,
}
if options.Mount {
diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go
index 4c2d29c06..9cd3b65f1 100644
--- a/vendor/github.com/containers/buildah/pkg/cli/common.go
+++ b/vendor/github.com/containers/buildah/pkg/cli/common.go
@@ -11,7 +11,9 @@ import (
"strings"
"github.com/containers/buildah"
+ "github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util"
+ "github.com/containers/common/pkg/config"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/spf13/pflag"
@@ -45,6 +47,7 @@ type NameSpaceResults struct {
// BudResults represents the results for Bud flags
type BudResults struct {
Annotation []string
+ Arch string
Authfile string
BuildArg []string
CacheFrom string
@@ -60,6 +63,7 @@ type BudResults struct {
Logfile string
Loglevel int
NoCache bool
+ OS string
Platform string
Pull bool
PullAlways bool
@@ -69,6 +73,7 @@ type BudResults struct {
Runtime string
RuntimeFlags []string
SignaturePolicy string
+ SignBy string
Squash bool
Tag []string
Target string
@@ -143,6 +148,7 @@ func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
// GetBudFlags returns common bud flags
func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs := pflag.FlagSet{}
+ fs.StringVar(&flags.Arch, "arch", runtime.GOARCH, "set the ARCH of the image to the provided value instead of the architecture of the host")
fs.StringArrayVar(&flags.Annotation, "annotation", []string{}, "Set metadata for an image (default [])")
fs.StringVar(&flags.Authfile, "authfile", GetDefaultAuthFile(), "path of the authentication file.")
fs.StringArrayVar(&flags.BuildArg, "build-arg", []string{}, "`argument=value` to supply to the builder")
@@ -159,7 +165,8 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.BoolVar(&flags.NoCache, "no-cache", false, "Do not use existing cached images for the container build. Build from the start with a new set of cached layers.")
fs.StringVar(&flags.Logfile, "logfile", "", "log to `file` instead of stdout/stderr")
fs.IntVar(&flags.Loglevel, "loglevel", 0, "adjust logging level (range from -2 to 3)")
- fs.StringVar(&flags.Platform, "platform", "", "CLI compatibility: no action or effect")
+ fs.StringVar(&flags.OS, "os", runtime.GOOS, "set the OS to the provided value instead of the current operating system of the host")
+ fs.StringVar(&flags.Platform, "platform", parse.DefaultPlatform(), "set the OS/ARCH to the provided value instead of the current operating system and architecture of the host (for example `linux/arm`)")
fs.BoolVar(&flags.Pull, "pull", true, "pull the image from the registry if newer or not present in store, if false, only pull the image if not present")
fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image even if the named image is present in store")
fs.BoolVar(&flags.PullNever, "pull-never", false, "do not pull the image, use the image present in store if available")
@@ -167,16 +174,22 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build")
// "runtime" definition moved to avoid name collision in podman build. Defined in cmd/buildah/bud.go.
fs.StringSliceVar(&flags.RuntimeFlags, "runtime-flag", []string{}, "add global flags for the container runtime")
+ fs.StringVar(&flags.SignBy, "sign-by", "", "sign the image using a GPG key with the specified `FINGERPRINT`")
fs.StringVar(&flags.SignaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)")
- fs.BoolVar(&flags.Squash, "squash", false, "Squash newly built layers into a single new layer.")
+ fs.BoolVar(&flags.Squash, "squash", false, "squash newly built layers into a single new layer")
fs.StringArrayVarP(&flags.Tag, "tag", "t", []string{}, "tagged `name` to apply to the built image")
fs.StringVar(&flags.Target, "target", "", "set the target build stage to build")
fs.BoolVar(&flags.TLSVerify, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry")
return fs
}
-func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, namespaceResults *NameSpaceResults) pflag.FlagSet {
+func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, namespaceResults *NameSpaceResults) (pflag.FlagSet, error) {
fs := pflag.FlagSet{}
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return fs, errors.Wrapf(err, "failed to get container config")
+ }
+
fs.StringSliceVar(&flags.AddHost, "add-host", []string{}, "add a custom host-to-IP mapping (`host:ip`) (default [])")
fs.StringVar(&flags.BlobCache, "blob-cache", "", "assume image blobs in the specified directory will be available for pushing")
if err := fs.MarkHidden("blob-cache"); err != nil {
@@ -190,10 +203,10 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
fs.Uint64VarP(&flags.CPUShares, "cpu-shares", "c", 0, "CPU shares (relative weight)")
fs.StringVar(&flags.CPUSetCPUs, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
fs.StringVar(&flags.CPUSetMems, "cpuset-mems", "", "memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.")
- fs.StringArrayVar(&flags.Devices, "device", []string{}, "Additional devices to be used within containers (default [])")
- fs.StringSliceVar(&flags.DNSSearch, "dns-search", []string{}, "Set custom DNS search domains")
- fs.StringSliceVar(&flags.DNSServers, "dns", []string{}, "Set custom DNS servers or disable it completely by setting it to 'none', which prevents the automatic creation of `/etc/resolv.conf`.")
- fs.StringSliceVar(&flags.DNSOptions, "dns-option", []string{}, "Set custom DNS options")
+ fs.StringArrayVar(&flags.Devices, "device", defaultContainerConfig.Containers.Devices, "Additional devices to be used within containers (default [])")
+ fs.StringSliceVar(&flags.DNSSearch, "dns-search", defaultContainerConfig.Containers.DNSSearches, "Set custom DNS search domains")
+ fs.StringSliceVar(&flags.DNSServers, "dns", defaultContainerConfig.Containers.DNSServers, "Set custom DNS servers or disable it completely by setting it to 'none', which prevents the automatic creation of `/etc/resolv.conf`.")
+ fs.StringSliceVar(&flags.DNSOptions, "dns-option", defaultContainerConfig.Containers.DNSOptions, "Set custom DNS options")
fs.BoolVar(&flags.HTTPProxy, "http-proxy", true, "pass through HTTP Proxy environment variables")
fs.StringVar(&flags.Isolation, "isolation", DefaultIsolation(), "`type` of process isolation to use. Use BUILDAH_ISOLATION environment variable to override.")
fs.StringVarP(&flags.Memory, "memory", "m", "", "memory limit (format: <number>[<unit>], where unit = b, k, m or g)")
@@ -207,9 +220,9 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
panic(fmt.Sprintf("error marking override-arch as hidden: %v", err))
}
fs.StringArrayVar(&flags.SecurityOpt, "security-opt", []string{}, "security options (default [])")
- fs.StringVar(&flags.ShmSize, "shm-size", "65536k", "size of '/dev/shm'. The format is `<number><unit>`.")
- fs.StringSliceVar(&flags.Ulimit, "ulimit", []string{}, "ulimit options (default [])")
- fs.StringArrayVarP(&flags.Volumes, "volume", "v", []string{}, "bind mount a volume into the container (default [])")
+ fs.StringVar(&flags.ShmSize, "shm-size", defaultContainerConfig.Containers.ShmSize, "size of '/dev/shm'. The format is `<number><unit>`.")
+ fs.StringSliceVar(&flags.Ulimit, "ulimit", defaultContainerConfig.Containers.DefaultUlimits, "ulimit options")
+ fs.StringArrayVarP(&flags.Volumes, "volume", "v", defaultContainerConfig.Containers.Volumes, "bind mount a volume into the container")
// Add in the usernamespace and namespaceflags
usernsFlags := GetUserNSFlags(usernsResults)
@@ -217,7 +230,7 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
fs.AddFlagSet(&usernsFlags)
fs.AddFlagSet(&namespaceFlags)
- return fs
+ return fs, nil
}
// UseLayers returns true if BUILDAH_LAYERS is set to "1" or "true"
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go
index d05f8075a..027ed103c 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go
@@ -9,6 +9,7 @@ import (
"net"
"os"
"path/filepath"
+ "runtime"
"strconv"
"strings"
"unicode"
@@ -51,8 +52,6 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
err error
)
- defaultLimits := getDefaultProcessLimits()
-
memVal, _ := c.Flags().GetString("memory")
if memVal != "" {
memoryLimit, err = units.RAMInBytes(memVal)
@@ -79,24 +78,33 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
}
noDNS = false
- dnsServers, _ := c.Flags().GetStringSlice("dns")
- for _, server := range dnsServers {
- if strings.ToLower(server) == "none" {
- noDNS = true
+ dnsServers := []string{}
+ if c.Flag("dns").Changed {
+ dnsServers, _ = c.Flags().GetStringSlice("dns")
+ for _, server := range dnsServers {
+ if strings.ToLower(server) == "none" {
+ noDNS = true
+ }
+ }
+ if noDNS && len(dnsServers) > 1 {
+ return nil, errors.Errorf("invalid --dns, --dns=none may not be used with any other --dns options")
}
- }
- if noDNS && len(dnsServers) > 1 {
- return nil, errors.Errorf("invalid --dns, --dns=none may not be used with any other --dns options")
}
- dnsSearch, _ := c.Flags().GetStringSlice("dns-search")
- if noDNS && len(dnsSearch) > 0 {
- return nil, errors.Errorf("invalid --dns-search, --dns-search may not be used with --dns=none")
+ dnsSearch := []string{}
+ if c.Flag("dns-search").Changed {
+ dnsSearch, _ = c.Flags().GetStringSlice("dns-search")
+ if noDNS && len(dnsSearch) > 0 {
+ return nil, errors.Errorf("invalid --dns-search, --dns-search may not be used with --dns=none")
+ }
}
- dnsOptions, _ := c.Flags().GetStringSlice("dns-option")
- if noDNS && len(dnsOptions) > 0 {
- return nil, errors.Errorf("invalid --dns-option, --dns-option may not be used with --dns=none")
+ dnsOptions := []string{}
+ if c.Flag("dns-search").Changed {
+ dnsOptions, _ = c.Flags().GetStringSlice("dns-option")
+ if noDNS && len(dnsOptions) > 0 {
+ return nil, errors.Errorf("invalid --dns-option, --dns-option may not be used with --dns=none")
+ }
}
if _, err := units.FromHumanSize(c.Flag("shm-size").Value.String()); err != nil {
@@ -110,7 +118,12 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
cpuQuota, _ := c.Flags().GetInt64("cpu-quota")
cpuShares, _ := c.Flags().GetUint64("cpu-shares")
httpProxy, _ := c.Flags().GetBool("http-proxy")
- ulimit, _ := c.Flags().GetStringSlice("ulimit")
+
+ ulimit := []string{}
+ if c.Flag("ulimit").Changed {
+ ulimit, _ = c.Flags().GetStringSlice("ulimit")
+ }
+
commonOpts := &buildah.CommonBuildOptions{
AddHost: addHost,
CgroupParent: c.Flag("cgroup-parent").Value.String(),
@@ -126,7 +139,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
Memory: memoryLimit,
MemorySwap: memorySwap,
ShmSize: c.Flag("shm-size").Value.String(),
- Ulimit: append(defaultLimits, ulimit...),
+ Ulimit: ulimit,
Volumes: volumes,
}
securityOpts, _ := c.Flags().GetStringArray("security-opt")
@@ -600,6 +613,46 @@ func getAuthFile(authfile string) string {
return os.Getenv("REGISTRY_AUTH_FILE")
}
+// PlatformFromOptions parses the operating system (os) and architecture (arch)
+// from the provided command line options.
+func PlatformFromOptions(c *cobra.Command) (os, arch string, err error) {
+ os = runtime.GOOS
+ arch = runtime.GOARCH
+
+ if selectedOS, err := c.Flags().GetString("os"); err == nil && selectedOS != runtime.GOOS {
+ os = selectedOS
+ }
+ if selectedArch, err := c.Flags().GetString("arch"); err == nil && selectedArch != runtime.GOARCH {
+ arch = selectedArch
+ }
+
+ if pf, err := c.Flags().GetString("platform"); err == nil && pf != DefaultPlatform() {
+ selectedOS, selectedArch, err := parsePlatform(pf)
+ if err != nil {
+ return "", "", errors.Wrap(err, "unable to parse platform")
+ }
+ arch = selectedArch
+ os = selectedOS
+ }
+
+ return os, arch, nil
+}
+
+const platformSep = "/"
+
+// DefaultPlatform returns the standard platform for the current system
+func DefaultPlatform() string {
+ return runtime.GOOS + platformSep + runtime.GOARCH
+}
+
+func parsePlatform(platform string) (os, arch string, err error) {
+ split := strings.Split(platform, platformSep)
+ if len(split) != 2 {
+ return "", "", errors.Errorf("invalid platform syntax for %q (use OS/ARCH)", platform)
+ }
+ return split[0], split[1], nil
+}
+
func parseCreds(creds string) (string, string) {
if creds == "" {
return "", ""
@@ -858,8 +911,7 @@ func defaultIsolation() (buildah.Isolation, error) {
}
// IsolationOption parses the --isolation flag.
-func IsolationOption(c *cobra.Command) (buildah.Isolation, error) {
- isolation, _ := c.Flags().GetString("isolation")
+func IsolationOption(isolation string) (buildah.Isolation, error) {
if isolation != "" {
switch strings.ToLower(isolation) {
case "oci":
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go b/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
index 906236cc3..33dc565d9 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
@@ -3,7 +3,6 @@
package parse
import (
- "fmt"
"os"
"path/filepath"
@@ -11,29 +10,16 @@ import (
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/devices"
"github.com/pkg/errors"
- "golang.org/x/sys/unix"
)
-func getDefaultProcessLimits() []string {
- rlim := unix.Rlimit{Cur: 1048576, Max: 1048576}
- defaultLimits := []string{}
- if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rlim); err == nil {
- defaultLimits = append(defaultLimits, fmt.Sprintf("nofile=%d:%d", rlim.Cur, rlim.Max))
- }
- if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil {
- defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max))
- }
- return defaultLimits
-}
-
func DeviceFromPath(device string) ([]configs.Device, error) {
var devs []configs.Device
src, dst, permissions, err := Device(device)
if err != nil {
return nil, err
}
- if unshare.IsRootless() {
- return nil, errors.Errorf("Renaming device %s to %s is not a supported in rootless containers", src, dst)
+ if unshare.IsRootless() && src != dst {
+ return nil, errors.Errorf("Renaming device %s to %s is not supported in rootless containers", src, dst)
}
srcInfo, err := os.Stat(src)
if err != nil {
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse_unsupported.go b/vendor/github.com/containers/buildah/pkg/parse/parse_unsupported.go
index 51138f860..61734bc11 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse_unsupported.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse_unsupported.go
@@ -12,6 +12,6 @@ func getDefaultProcessLimits() []string {
return []string{}
}
-func DeviceFromPath(device string) (configs.Device, error) {
- return configs.Device{}, fmt.Errorf("devices not supported")
+func DeviceFromPath(device string) ([]configs.Device, error) {
+ return []configs.Device{}, fmt.Errorf("devices not supported")
}
diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go
index 300f3b396..4a38abeab 100644
--- a/vendor/github.com/containers/buildah/pull.go
+++ b/vendor/github.com/containers/buildah/pull.go
@@ -3,12 +3,11 @@ package buildah
import (
"context"
"io"
-
"strings"
+ "time"
"github.com/containers/buildah/pkg/blobcache"
"github.com/containers/buildah/util"
- cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker"
dockerarchive "github.com/containers/image/v5/docker/archive"
@@ -49,6 +48,14 @@ type PullOptions struct {
// AllTags is a boolean value that determines if all tagged images
// will be downloaded from the repository. The default is false.
AllTags bool
+ // RemoveSignatures causes any existing signatures for the image to be
+ // discarded when pulling it.
+ RemoveSignatures bool
+ // MaxRetries is the maximum number of attempts we'll make to pull any
+ // one image from the external registry if the first attempt fails.
+ MaxRetries int
+ // RetryDelay is how long to wait before retrying a pull attempt.
+ RetryDelay time.Duration
}
func localImageNameForReference(ctx context.Context, store storage.Store, srcRef types.ImageReference) (string, error) {
@@ -63,6 +70,7 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef
if err != nil {
return "", errors.Wrapf(err, "error opening tarfile %q as a source image", file)
}
+ defer tarSource.Close()
manifest, err := tarSource.LoadTarManifest()
if err != nil {
return "", errors.Errorf("error retrieving manifest.json from tarfile %q: %v", file, err)
@@ -154,6 +162,8 @@ func Pull(ctx context.Context, imageName string, options PullOptions) (imageID s
SystemContext: systemContext,
BlobDirectory: options.BlobDirectory,
ReportWriter: options.ReportWriter,
+ MaxPullRetries: options.MaxRetries,
+ PullRetryDelay: options.RetryDelay,
}
storageRef, transport, img, err := resolveImage(ctx, systemContext, options.Store, boptions)
@@ -260,7 +270,7 @@ func pullImage(ctx context.Context, store storage.Store, srcRef types.ImageRefer
}()
logrus.Debugf("copying %q to %q", transports.ImageName(srcRef), destName)
- if _, err := cp.Image(ctx, policyContext, maybeCachedDestRef, srcRef, getCopyOptions(store, options.ReportWriter, sc, nil, "")); err != nil {
+ if _, err := retryCopyImage(ctx, policyContext, maybeCachedDestRef, srcRef, srcRef, "pull", getCopyOptions(store, options.ReportWriter, sc, nil, "", options.RemoveSignatures, ""), options.MaxRetries, options.RetryDelay); err != nil {
logrus.Debugf("error copying src image [%q] to dest image [%q] err: %v", transports.ImageName(srcRef), destName, err)
return nil, err
}
diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go
index e7994e388..d2c0abf9b 100644
--- a/vendor/github.com/containers/buildah/run_linux.go
+++ b/vendor/github.com/containers/buildah/run_linux.go
@@ -26,6 +26,8 @@ import (
"github.com/containers/buildah/pkg/overlay"
"github.com/containers/buildah/pkg/secrets"
"github.com/containers/buildah/util"
+ "github.com/containers/common/pkg/capabilities"
+ "github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/unshare"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
@@ -89,7 +91,11 @@ func (b *Builder) Run(command []string, options RunOptions) error {
return err
}
- b.configureEnvironment(g, options)
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return errors.Wrapf(err, "failed to get container config")
+ }
+ b.configureEnvironment(g, options, defaultContainerConfig.Containers.Env)
if b.CommonBuildOpts == nil {
return errors.Errorf("Invalid format on container you must recreate the container")
@@ -291,8 +297,12 @@ func addCommonOptsToSpec(commonOpts *CommonBuildOptions, g *generate.Generator)
g.SetLinuxCgroupsPath(commonOpts.CgroupParent)
}
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return errors.Wrapf(err, "failed to get container config")
+ }
// Other process resource limits
- if err := addRlimits(commonOpts.Ulimit, g); err != nil {
+ if err := addRlimits(commonOpts.Ulimit, g, defaultContainerConfig.Containers.DefaultUlimits); err != nil {
return err
}
@@ -506,6 +516,11 @@ func (b *Builder) addNetworkConfig(rdir, hostPath string, chownOpts *idtools.IDP
nameservers := resolvconf.GetNameservers(contents, types.IP)
options := resolvconf.GetOptions(contents)
+ defaultContainerConfig, err := config.Default()
+ if err != nil {
+ return "", errors.Wrapf(err, "failed to get container config")
+ }
+ dnsSearch = append(defaultContainerConfig.Containers.DNSSearches, dnsSearch...)
if len(dnsSearch) > 0 {
search = dnsSearch
}
@@ -519,6 +534,7 @@ func (b *Builder) addNetworkConfig(rdir, hostPath string, chownOpts *idtools.IDP
}
}
+ dnsServers = append(defaultContainerConfig.Containers.DNSServers, dnsServers...)
if len(dnsServers) != 0 {
dns, err := getDNSIP(dnsServers)
if err != nil {
@@ -530,6 +546,7 @@ func (b *Builder) addNetworkConfig(rdir, hostPath string, chownOpts *idtools.IDP
}
}
+ dnsOptions = append(defaultContainerConfig.Containers.DNSOptions, dnsOptions...)
if len(dnsOptions) != 0 {
options = dnsOptions
}
@@ -661,6 +678,11 @@ func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork b
runtime := options.Runtime
if runtime == "" {
runtime = util.Runtime()
+
+ localRuntime := util.FindLocalRuntime(runtime)
+ if localRuntime != "" {
+ runtime = localRuntime
+ }
}
// Default to just passing down our stdio.
@@ -1599,12 +1621,13 @@ func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts
return mounts
}
-func addRlimits(ulimit []string, g *generate.Generator) error {
+func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string) error {
var (
ul *units.Ulimit
err error
)
+ ulimit = append(defaultUlimits, ulimit...)
for _, u := range ulimit {
if ul, err = units.ParseUlimit(u); err != nil {
return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u)
@@ -1799,21 +1822,27 @@ func setupCapDrop(g *generate.Generator, caps ...string) error {
return nil
}
-func setupCapabilities(g *generate.Generator, firstAdds, firstDrops, secondAdds, secondDrops []string) error {
+func setupCapabilities(g *generate.Generator, defaultCapabilities, adds, drops []string) error {
g.ClearProcessCapabilities()
- if err := setupCapAdd(g, util.DefaultCapabilities...); err != nil {
+ if err := setupCapAdd(g, defaultCapabilities...); err != nil {
return err
}
- if err := setupCapAdd(g, firstAdds...); err != nil {
- return err
+ for _, c := range adds {
+ if strings.ToLower(c) == "all" {
+ adds = capabilities.AllCapabilities()
+ break
+ }
}
- if err := setupCapDrop(g, firstDrops...); err != nil {
- return err
+ for _, c := range drops {
+ if strings.ToLower(c) == "all" {
+ g.ClearProcessCapabilities()
+ return nil
+ }
}
- if err := setupCapAdd(g, secondAdds...); err != nil {
+ if err := setupCapAdd(g, adds...); err != nil {
return err
}
- return setupCapDrop(g, secondDrops...)
+ return setupCapDrop(g, drops...)
}
// Search for a command that isn't given as an absolute path using the $PATH
@@ -1880,7 +1909,7 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti
if err != nil {
return "", err
}
- if err := setupCapabilities(g, b.AddCapabilities, b.DropCapabilities, options.AddCapabilities, options.DropCapabilities); err != nil {
+ if err := setupCapabilities(g, b.Capabilities, options.AddCapabilities, options.DropCapabilities); err != nil {
return "", err
}
g.SetProcessUID(user.UID)
@@ -1899,8 +1928,9 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti
return homeDir, nil
}
-func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions) {
+func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions, defaultEnv []string) {
g.ClearProcessEnv()
+
if b.CommonBuildOpts.HTTPProxy {
for _, envSpec := range []string{
"http_proxy",
@@ -1919,7 +1949,7 @@ func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions
}
}
- for _, envSpec := range append(b.Env(), options.Env...) {
+ for _, envSpec := range append(append(defaultEnv, b.Env()...), options.Env...) {
env := strings.SplitN(envSpec, "=", 2)
if len(env) > 1 {
g.AddProcessEnv(env[0], env[1])
diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go
index 617af7b32..05d661b58 100644
--- a/vendor/github.com/containers/buildah/util/util.go
+++ b/vendor/github.com/containers/buildah/util/util.go
@@ -7,14 +7,16 @@ import (
"os"
"path"
"strings"
+ "sync"
"syscall"
- "github.com/containers/common/pkg/cgroups"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/image/v5/signature"
is "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/transports"
+ "github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/docker/distribution/registry/api/errcode"
@@ -209,6 +211,36 @@ func FindImage(store storage.Store, firstRegistry string, systemContext *types.S
return ref, img, nil
}
+// ResolveNameToReferences tries to create a list of possible references
+// (including their transports) from the provided image name.
+func ResolveNameToReferences(
+ store storage.Store,
+ systemContext *types.SystemContext,
+ image string,
+) (refs []types.ImageReference, err error) {
+ names, transport, _, err := ResolveName(image, "", systemContext, store)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing name %q", image)
+ }
+
+ if transport != DefaultTransport {
+ transport += ":"
+ }
+
+ for _, name := range names {
+ ref, err := alltransports.ParseImageName(transport + name)
+ if err != nil {
+ logrus.Debugf("error parsing reference to image %q: %v", name, err)
+ continue
+ }
+ refs = append(refs, ref)
+ }
+ if len(refs) == 0 {
+ return nil, errors.Errorf("error locating images with names %v", names)
+ }
+ return refs, nil
+}
+
// AddImageNames adds the specified names to the specified image.
func AddImageNames(store storage.Store, firstRegistry string, systemContext *types.SystemContext, image *storage.Image, addNames []string) error {
names, err := ExpandNames(addNames, firstRegistry, systemContext, store)
@@ -252,7 +284,7 @@ func Runtime() string {
}
// Need to switch default until runc supports cgroups v2
- if unified, _ := cgroups.IsCgroup2UnifiedMode(); unified {
+ if unified, _ := IsCgroup2UnifiedMode(); unified {
return "crun"
}
@@ -395,3 +427,39 @@ func TruncateString(str string, to int) string {
}
return newStr
}
+
+var (
+ isUnifiedOnce sync.Once
+ isUnified bool
+ isUnifiedErr error
+)
+
+// fileExistsAndNotADir - Check to see if a file exists
+// and that it is not a directory.
+func fileExistsAndNotADir(path string) bool {
+ file, err := os.Stat(path)
+
+ if file == nil || err != nil || os.IsNotExist(err) {
+ return false
+ }
+ return !file.IsDir()
+}
+
+// FindLocalRuntime find the local runtime of the
+// system searching through the config file for
+// possible locations.
+func FindLocalRuntime(runtime string) string {
+ var localRuntime string
+ conf, err := config.Default()
+ if err != nil {
+ logrus.Debugf("Error loading container config when searching for local runtime.")
+ return localRuntime
+ }
+ for _, val := range conf.Libpod.OCIRuntimes[runtime] {
+ if fileExistsAndNotADir(val) {
+ localRuntime = val
+ break
+ }
+ }
+ return localRuntime
+}
diff --git a/vendor/github.com/containers/buildah/util/util_linux.go b/vendor/github.com/containers/buildah/util/util_linux.go
new file mode 100644
index 000000000..cca1f9e7e
--- /dev/null
+++ b/vendor/github.com/containers/buildah/util/util_linux.go
@@ -0,0 +1,20 @@
+package util
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
+func IsCgroup2UnifiedMode() (bool, error) {
+ isUnifiedOnce.Do(func() {
+ var st syscall.Statfs_t
+ if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
+ isUnified, isUnifiedErr = false, err
+ } else {
+ isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil
+ }
+ })
+ return isUnified, isUnifiedErr
+}
diff --git a/vendor/github.com/containers/buildah/util/util_unsupported.go b/vendor/github.com/containers/buildah/util/util_unsupported.go
new file mode 100644
index 000000000..05a68f60b
--- /dev/null
+++ b/vendor/github.com/containers/buildah/util/util_unsupported.go
@@ -0,0 +1,8 @@
+// +build !linux
+
+package util
+
+// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
+func IsCgroup2UnifiedMode() (bool, error) {
+ return false, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
new file mode 100644
index 000000000..a57c048bc
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
@@ -0,0 +1,142 @@
+package capabilities
+
+// Copyright 2013-2018 Docker, Inc.
+
+// NOTE: this package has been copied from github.com/docker/docker but been
+// changed significantly to fit the needs of libpod.
+
+import (
+ "strings"
+
+ "github.com/pkg/errors"
+ "github.com/syndtr/gocapability/capability"
+)
+
+var (
+ // Used internally and populated during init().
+ capabilityList []string
+
+ // ErrUnknownCapability is thrown when an unknown capability is processed.
+ ErrUnknownCapability = errors.New("unknown capability")
+
+ // ContainerImageLabels - label can indicate the required
+ // capabilities required by containers to run the container image.
+ ContainerImageLabels = []string{"io.containers.capabilities"}
+)
+
+// All is a special value used to add/drop all known capababilities.
+// Useful on the CLI for `--cap-add=all` etc.
+const All = "ALL"
+
+func init() {
+ last := capability.CAP_LAST_CAP
+ // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
+ if last == capability.Cap(63) {
+ last = capability.CAP_BLOCK_SUSPEND
+ }
+ for _, cap := range capability.List() {
+ if cap > last {
+ continue
+ }
+ capabilityList = append(capabilityList, "CAP_"+strings.ToUpper(cap.String()))
+ }
+}
+
+// stringInSlice determines if a string is in a string slice, returns bool
+func stringInSlice(s string, sl []string) bool {
+ for _, i := range sl {
+ if i == s {
+ return true
+ }
+ }
+ return false
+}
+
+// AllCapabilities returns all known capabilities.
+func AllCapabilities() []string {
+ return capabilityList
+}
+
+// normalizeCapabilities normalizes caps by adding a "CAP_" prefix (if not yet
+// present).
+func normalizeCapabilities(caps []string) ([]string, error) {
+ normalized := make([]string, len(caps))
+ for i, c := range caps {
+ c = strings.ToUpper(c)
+ if c == All {
+ normalized = append(normalized, c)
+ continue
+ }
+ if !strings.HasPrefix(c, "CAP_") {
+ c = "CAP_" + c
+ }
+ if !stringInSlice(c, capabilityList) {
+ return nil, errors.Wrapf(ErrUnknownCapability, "%q", c)
+ }
+ normalized[i] = c
+ }
+ return normalized, nil
+}
+
+// ValidateCapabilities validates if caps only contains valid capabilities.
+func ValidateCapabilities(caps []string) error {
+ for _, c := range caps {
+ if !stringInSlice(c, capabilityList) {
+ return errors.Wrapf(ErrUnknownCapability, "%q", c)
+ }
+ }
+ return nil
+}
+
+// MergeCapabilities computes a set of capabilities by adding capapbitilities
+// to or dropping them from base.
+//
+// Note that "ALL" will cause all known capabilities to be added/dropped but
+// the ones specified to be dropped/added.
+func MergeCapabilities(base, adds, drops []string) ([]string, error) {
+ if len(adds) == 0 && len(drops) == 0 {
+ // Nothing to tweak; we're done
+ return base, nil
+ }
+
+ capDrop, err := normalizeCapabilities(drops)
+ if err != nil {
+ return nil, err
+ }
+ capAdd, err := normalizeCapabilities(adds)
+ if err != nil {
+ return nil, err
+ }
+
+ // Make sure that capDrop and capAdd are distinct sets.
+ for _, drop := range capDrop {
+ if stringInSlice(drop, capAdd) {
+ return nil, errors.Errorf("capability %q cannot be dropped and added", drop)
+ }
+ }
+
+ var caps []string
+
+ switch {
+ case stringInSlice(All, capAdd):
+ // Add all capabilities except ones on capDrop
+ for _, c := range capabilityList {
+ if !stringInSlice(c, capDrop) {
+ caps = append(caps, c)
+ }
+ }
+ case stringInSlice(All, capDrop):
+ // "Drop" all capabilities; use what's in capAdd instead
+ caps = capAdd
+ default:
+ // First drop some capabilities
+ for _, c := range base {
+ if !stringInSlice(c, capDrop) {
+ caps = append(caps, c)
+ }
+ }
+ // Then add the list of capabilities from capAdd
+ caps = append(caps, capAdd...)
+ }
+ return caps, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/blkio.go b/vendor/github.com/containers/common/pkg/cgroups/blkio.go
deleted file mode 100644
index bacd4eb93..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/blkio.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package cgroups
-
-import (
- "bufio"
- "fmt"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
-)
-
-type blkioHandler struct {
-}
-
-func getBlkioHandler() *blkioHandler {
- return &blkioHandler{}
-}
-
-// Apply set the specified constraints
-func (c *blkioHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
- if res.BlockIO == nil {
- return nil
- }
- return fmt.Errorf("blkio apply function not implemented yet")
-}
-
-// Create the cgroup
-func (c *blkioHandler) Create(ctr *CgroupControl) (bool, error) {
- if ctr.cgroup2 {
- return false, nil
- }
- return ctr.createCgroupDirectory(Blkio)
-}
-
-// Destroy the cgroup
-func (c *blkioHandler) Destroy(ctr *CgroupControl) error {
- return rmDirRecursively(ctr.getCgroupv1Path(Blkio))
-}
-
-// Stat fills a metrics structure with usage stats for the controller
-func (c *blkioHandler) Stat(ctr *CgroupControl, m *Metrics) error {
- var ioServiceBytesRecursive []BlkIOEntry
-
- if ctr.cgroup2 {
- // more details on the io.stat file format:X https://facebookmicrosites.github.io/cgroup2/docs/io-controller.html
- values, err := readCgroup2MapFile(ctr, "io.stat")
- if err != nil {
- return err
- }
- for k, v := range values {
- d := strings.Split(k, ":")
- if len(d) != 2 {
- continue
- }
- minor, err := strconv.ParseUint(d[0], 10, 0)
- if err != nil {
- return err
- }
- major, err := strconv.ParseUint(d[1], 10, 0)
- if err != nil {
- return err
- }
-
- for _, item := range v {
- d := strings.Split(item, "=")
- if len(d) != 2 {
- continue
- }
- op := d[0]
-
- // Accommodate the cgroup v1 naming
- switch op {
- case "rbytes":
- op = "read"
- case "wbytes":
- op = "write"
- }
-
- value, err := strconv.ParseUint(d[1], 10, 0)
- if err != nil {
- return err
- }
-
- entry := BlkIOEntry{
- Op: op,
- Major: major,
- Minor: minor,
- Value: value,
- }
- ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry)
- }
- }
- } else {
- BlkioRoot := ctr.getCgroupv1Path(Blkio)
-
- p := filepath.Join(BlkioRoot, "blkio.throttle.io_service_bytes_recursive")
- f, err := os.Open(p)
- if err != nil {
- if os.IsNotExist(err) {
- return nil
- }
- return errors.Wrapf(err, "open %s", p)
- }
- defer f.Close()
-
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- parts := strings.Fields(line)
- if len(parts) < 3 {
- continue
- }
- d := strings.Split(parts[0], ":")
- if len(d) != 2 {
- continue
- }
- minor, err := strconv.ParseUint(d[0], 10, 0)
- if err != nil {
- return err
- }
- major, err := strconv.ParseUint(d[1], 10, 0)
- if err != nil {
- return err
- }
-
- op := parts[1]
-
- value, err := strconv.ParseUint(parts[2], 10, 0)
- if err != nil {
- return err
- }
- entry := BlkIOEntry{
- Op: op,
- Major: major,
- Minor: minor,
- Value: value,
- }
- ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry)
- }
- if err := scanner.Err(); err != nil {
- return errors.Wrapf(err, "parse %s", p)
- }
- }
- m.Blkio = BlkioMetrics{IoServiceBytesRecursive: ioServiceBytesRecursive}
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups.go
deleted file mode 100644
index f8a9022f4..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/cgroups.go
+++ /dev/null
@@ -1,564 +0,0 @@
-package cgroups
-
-import (
- "bufio"
- "fmt"
- "io/ioutil"
- "math"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- "github.com/containers/common/pkg/unshare"
- systemdDbus "github.com/coreos/go-systemd/dbus"
- "github.com/godbus/dbus"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-var (
- // ErrCgroupDeleted means the cgroup was deleted
- ErrCgroupDeleted = errors.New("cgroup deleted")
- // ErrCgroupV1Rootless means the cgroup v1 were attempted to be used in rootless environmen
- ErrCgroupV1Rootless = errors.New("no support for CGroups V1 in rootless environments")
-)
-
-// CgroupControl controls a cgroup hierarchy
-type CgroupControl struct {
- cgroup2 bool
- path string
- systemd bool
- // List of additional cgroup subsystems joined that
- // do not have a custom handler.
- additionalControllers []controller
-}
-
-// CPUUsage keeps stats for the CPU usage (unit: nanoseconds)
-type CPUUsage struct {
- Kernel uint64
- Total uint64
- PerCPU []uint64
-}
-
-// MemoryUsage keeps stats for the memory usage
-type MemoryUsage struct {
- Usage uint64
- Limit uint64
-}
-
-// CPUMetrics keeps stats for the CPU usage
-type CPUMetrics struct {
- Usage CPUUsage
-}
-
-// BlkIOEntry describes an entry in the blkio stats
-type BlkIOEntry struct {
- Op string
- Major uint64
- Minor uint64
- Value uint64
-}
-
-// BlkioMetrics keeps usage stats for the blkio cgroup controller
-type BlkioMetrics struct {
- IoServiceBytesRecursive []BlkIOEntry
-}
-
-// MemoryMetrics keeps usage stats for the memory cgroup controller
-type MemoryMetrics struct {
- Usage MemoryUsage
-}
-
-// PidsMetrics keeps usage stats for the pids cgroup controller
-type PidsMetrics struct {
- Current uint64
-}
-
-// Metrics keeps usage stats for the cgroup controllers
-type Metrics struct {
- CPU CPUMetrics
- Blkio BlkioMetrics
- Memory MemoryMetrics
- Pids PidsMetrics
-}
-
-type controller struct {
- name string
- symlink bool
-}
-
-type controllerHandler interface {
- Create(*CgroupControl) (bool, error)
- Apply(*CgroupControl, *spec.LinuxResources) error
- Destroy(*CgroupControl) error
- Stat(*CgroupControl, *Metrics) error
-}
-
-const (
- cgroupRoot = "/sys/fs/cgroup"
- _cgroup2SuperMagic = 0x63677270
- // CPU is the cpu controller
- CPU = "cpu"
- // CPUAcct is the cpuacct controller
- CPUAcct = "cpuacct"
- // CPUset is the cpuset controller
- CPUset = "cpuset"
- // Memory is the memory controller
- Memory = "memory"
- // Pids is the pids controller
- Pids = "pids"
- // Blkio is the blkio controller
- Blkio = "blkio"
-)
-
-var handlers map[string]controllerHandler
-
-func init() {
- handlers = make(map[string]controllerHandler)
- handlers[CPU] = getCPUHandler()
- handlers[CPUset] = getCpusetHandler()
- handlers[Memory] = getMemoryHandler()
- handlers[Pids] = getPidsHandler()
- handlers[Blkio] = getBlkioHandler()
-}
-
-// getAvailableControllers get the available controllers
-func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]controller, error) {
- if cgroup2 {
- return nil, fmt.Errorf("getAvailableControllers not implemented yet for cgroup v2")
- }
-
- infos, err := ioutil.ReadDir(cgroupRoot)
- if err != nil {
- return nil, errors.Wrapf(err, "read directory %s", cgroupRoot)
- }
- var controllers []controller
- for _, i := range infos {
- name := i.Name()
- if _, found := exclude[name]; found {
- continue
- }
- c := controller{
- name: name,
- symlink: !i.IsDir(),
- }
- controllers = append(controllers, c)
- }
- return controllers, nil
-}
-
-// getCgroupv1Path is a helper function to get the cgroup v1 path
-func (c *CgroupControl) getCgroupv1Path(name string) string {
- return filepath.Join(cgroupRoot, name, c.path)
-}
-
-// createCgroupv2Path creates the cgroupv2 path and enables all the available controllers
-func createCgroupv2Path(path string) (Err error) {
- content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
- if err != nil {
- return errors.Wrapf(err, "read /sys/fs/cgroup/cgroup.controllers")
- }
- if !strings.HasPrefix(path, "/sys/fs/cgroup/") {
- return fmt.Errorf("invalid cgroup path %s", path)
- }
-
- res := ""
- for i, c := range strings.Split(strings.TrimSpace(string(content)), " ") {
- if i == 0 {
- res = fmt.Sprintf("+%s", c)
- } else {
- res = res + fmt.Sprintf(" +%s", c)
- }
- }
- resByte := []byte(res)
-
- current := "/sys/fs"
- elements := strings.Split(path, "/")
- for i, e := range elements[3:] {
- current = filepath.Join(current, e)
- if i > 0 {
- if err := os.Mkdir(current, 0755); err != nil {
- if !os.IsExist(err) {
- return errors.Wrapf(err, "mkdir %s", path)
- }
- } else {
- // If the directory was created, be sure it is not left around on errors.
- defer func() {
- if Err != nil {
- os.Remove(current)
- }
- }()
- }
- }
- // We enable the controllers for all the path components except the last one. It is not allowed to add
- // PIDs if there are already enabled controllers.
- if i < len(elements[3:])-1 {
- if err := ioutil.WriteFile(filepath.Join(current, "cgroup.subtree_control"), resByte, 0755); err != nil {
- return errors.Wrapf(err, "write %s", filepath.Join(current, "cgroup.subtree_control"))
- }
- }
- }
- return nil
-}
-
-// initialize initializes the specified hierarchy
-func (c *CgroupControl) initialize() (err error) {
- createdSoFar := map[string]controllerHandler{}
- defer func() {
- if err != nil {
- for name, ctr := range createdSoFar {
- if err := ctr.Destroy(c); err != nil {
- logrus.Warningf("error cleaning up controller %s for %s", name, c.path)
- }
- }
- }
- }()
- if c.cgroup2 {
- if err := createCgroupv2Path(filepath.Join(cgroupRoot, c.path)); err != nil {
- return errors.Wrapf(err, "error creating cgroup path %s", c.path)
- }
- }
- for name, handler := range handlers {
- created, err := handler.Create(c)
- if err != nil {
- return err
- }
- if created {
- createdSoFar[name] = handler
- }
- }
-
- if !c.cgroup2 {
- // We won't need to do this for cgroup v2
- for _, ctr := range c.additionalControllers {
- if ctr.symlink {
- continue
- }
- path := c.getCgroupv1Path(ctr.name)
- if err := os.MkdirAll(path, 0755); err != nil {
- return errors.Wrapf(err, "error creating cgroup path %s for %s", path, ctr.name)
- }
- }
- }
-
- return nil
-}
-
-func (c *CgroupControl) createCgroupDirectory(controller string) (bool, error) {
- cPath := c.getCgroupv1Path(controller)
- _, err := os.Stat(cPath)
- if err == nil {
- return false, nil
- }
-
- if !os.IsNotExist(err) {
- return false, err
- }
-
- if err := os.MkdirAll(cPath, 0755); err != nil {
- return false, errors.Wrapf(err, "error creating cgroup for %s", controller)
- }
- return true, nil
-}
-
-func readFileAsUint64(path string) (uint64, error) {
- data, err := ioutil.ReadFile(path)
- if err != nil {
- return 0, errors.Wrapf(err, "open %s", path)
- }
- v := cleanString(string(data))
- if v == "max" {
- return math.MaxUint64, nil
- }
- ret, err := strconv.ParseUint(v, 10, 0)
- if err != nil {
- return ret, errors.Wrapf(err, "parse %s from %s", v, path)
- }
- return ret, nil
-}
-
-// New creates a new cgroup control
-func New(path string, resources *spec.LinuxResources) (*CgroupControl, error) {
- cgroup2, err := IsCgroup2UnifiedMode()
- if err != nil {
- return nil, err
- }
- control := &CgroupControl{
- cgroup2: cgroup2,
- path: path,
- }
-
- if !cgroup2 {
- controllers, err := getAvailableControllers(handlers, false)
- if err != nil {
- return nil, err
- }
- control.additionalControllers = controllers
- }
-
- if err := control.initialize(); err != nil {
- return nil, err
- }
-
- return control, nil
-}
-
-// NewSystemd creates a new cgroup control
-func NewSystemd(path string) (*CgroupControl, error) {
- cgroup2, err := IsCgroup2UnifiedMode()
- if err != nil {
- return nil, err
- }
- control := &CgroupControl{
- cgroup2: cgroup2,
- path: path,
- systemd: true,
- }
- return control, nil
-}
-
-// Load loads an existing cgroup control
-func Load(path string) (*CgroupControl, error) {
- cgroup2, err := IsCgroup2UnifiedMode()
- if err != nil {
- return nil, err
- }
- control := &CgroupControl{
- cgroup2: cgroup2,
- path: path,
- systemd: false,
- }
- if !cgroup2 {
- controllers, err := getAvailableControllers(handlers, false)
- if err != nil {
- return nil, err
- }
- control.additionalControllers = controllers
- }
- if !cgroup2 {
- for name := range handlers {
- p := control.getCgroupv1Path(name)
- if _, err := os.Stat(p); err != nil {
- if os.IsNotExist(err) {
- if unshare.IsRootless() {
- return nil, ErrCgroupV1Rootless
- }
- // compatible with the error code
- // used by containerd/cgroups
- return nil, ErrCgroupDeleted
- }
- }
- }
- }
- return control, nil
-}
-
-// CreateSystemdUnit creates the systemd cgroup
-func (c *CgroupControl) CreateSystemdUnit(path string) error {
- if !c.systemd {
- return fmt.Errorf("the cgroup controller is not using systemd")
- }
-
- conn, err := systemdDbus.New()
- if err != nil {
- return err
- }
- defer conn.Close()
-
- return systemdCreate(path, conn)
-}
-
-// GetUserConnection returns an user connection to D-BUS
-func GetUserConnection(uid int) (*systemdDbus.Conn, error) {
- return systemdDbus.NewConnection(func() (*dbus.Conn, error) {
- return dbusAuthConnection(uid, dbus.SessionBusPrivate)
- })
-}
-
-// CreateSystemdUserUnit creates the systemd cgroup for the specified user
-func (c *CgroupControl) CreateSystemdUserUnit(path string, uid int) error {
- if !c.systemd {
- return fmt.Errorf("the cgroup controller is not using systemd")
- }
-
- conn, err := GetUserConnection(uid)
- if err != nil {
- return err
- }
- defer conn.Close()
-
- return systemdCreate(path, conn)
-}
-
-func dbusAuthConnection(uid int, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
- conn, err := createBus()
- if err != nil {
- return nil, err
- }
-
- methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(uid))}
-
- err = conn.Auth(methods)
- if err != nil {
- conn.Close()
- return nil, err
- }
- if err := conn.Hello(); err != nil {
- return nil, err
- }
-
- return conn, nil
-}
-
-// Delete cleans a cgroup
-func (c *CgroupControl) Delete() error {
- return c.DeleteByPath(c.path)
-}
-
-// rmDirRecursively delete recursively a cgroup directory.
-// It differs from os.RemoveAll as it doesn't attempt to unlink files.
-// On cgroupfs we are allowed only to rmdir empty directories.
-func rmDirRecursively(path string) error {
- if err := os.Remove(path); err == nil || os.IsNotExist(err) {
- return nil
- }
- entries, err := ioutil.ReadDir(path)
- if err != nil {
- return errors.Wrapf(err, "read %s", path)
- }
- for _, i := range entries {
- if i.IsDir() {
- if err := rmDirRecursively(filepath.Join(path, i.Name())); err != nil {
- return err
- }
- }
- }
- if err := os.Remove(path); err != nil {
- if !os.IsNotExist(err) {
- return errors.Wrapf(err, "remove %s", path)
- }
- }
- return nil
-}
-
-// DeleteByPathConn deletes the specified cgroup path using the specified
-// dbus connection if needed.
-func (c *CgroupControl) DeleteByPathConn(path string, conn *systemdDbus.Conn) error {
- if c.systemd {
- return systemdDestroyConn(path, conn)
- }
- if c.cgroup2 {
- return rmDirRecursively(filepath.Join(cgroupRoot, c.path))
- }
- var lastError error
- for _, h := range handlers {
- if err := h.Destroy(c); err != nil {
- lastError = err
- }
- }
-
- for _, ctr := range c.additionalControllers {
- if ctr.symlink {
- continue
- }
- p := c.getCgroupv1Path(ctr.name)
- if err := rmDirRecursively(p); err != nil {
- lastError = errors.Wrapf(err, "remove %s", p)
- }
- }
- return lastError
-}
-
-// DeleteByPath deletes the specified cgroup path
-func (c *CgroupControl) DeleteByPath(path string) error {
- if c.systemd {
- conn, err := systemdDbus.New()
- if err != nil {
- return err
- }
- defer conn.Close()
- return c.DeleteByPathConn(path, conn)
- }
- return c.DeleteByPathConn(path, nil)
-}
-
-// Update updates the cgroups
-func (c *CgroupControl) Update(resources *spec.LinuxResources) error {
- for _, h := range handlers {
- if err := h.Apply(c, resources); err != nil {
- return err
- }
- }
- return nil
-}
-
-// AddPid moves the specified pid to the cgroup
-func (c *CgroupControl) AddPid(pid int) error {
- pidString := []byte(fmt.Sprintf("%d\n", pid))
-
- if c.cgroup2 {
- p := filepath.Join(cgroupRoot, c.path, "cgroup.procs")
- if err := ioutil.WriteFile(p, pidString, 0644); err != nil {
- return errors.Wrapf(err, "write %s", p)
- }
- return nil
- }
-
- var names []string
- for n := range handlers {
- names = append(names, n)
- }
-
- for _, c := range c.additionalControllers {
- if !c.symlink {
- names = append(names, c.name)
- }
- }
-
- for _, n := range names {
- p := filepath.Join(c.getCgroupv1Path(n), "tasks")
- if err := ioutil.WriteFile(p, pidString, 0644); err != nil {
- return errors.Wrapf(err, "write %s", p)
- }
- }
- return nil
-}
-
-// Stat returns usage statistics for the cgroup
-func (c *CgroupControl) Stat() (*Metrics, error) {
- m := Metrics{}
- for _, h := range handlers {
- if err := h.Stat(c, &m); err != nil {
- return nil, err
- }
- }
- return &m, nil
-}
-
-func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) {
- ret := map[string][]string{}
- p := filepath.Join(cgroupRoot, ctr.path, name)
- f, err := os.Open(p)
- if err != nil {
- if os.IsNotExist(err) {
- return ret, nil
- }
- return nil, errors.Wrapf(err, "open file %s", p)
- }
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- parts := strings.Fields(line)
- if len(parts) < 2 {
- continue
- }
- ret[parts[0]] = parts[1:]
- }
- if err := scanner.Err(); err != nil {
- return nil, errors.Wrapf(err, "parsing file %s", p)
- }
- return ret, nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go
deleted file mode 100644
index 2a36777d4..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// +build linux
-
-package cgroups
-
-import (
- "bufio"
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "sync"
- "syscall"
-
- "github.com/pkg/errors"
-)
-
-var (
- isUnifiedOnce sync.Once
- isUnified bool
- isUnifiedErr error
-)
-
-// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
-func IsCgroup2UnifiedMode() (bool, error) {
- isUnifiedOnce.Do(func() {
- var st syscall.Statfs_t
- if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
- isUnified, isUnifiedErr = false, err
- } else {
- isUnified, isUnifiedErr = st.Type == _cgroup2SuperMagic, nil
- }
- })
- return isUnified, isUnifiedErr
-}
-
-// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the
-// current cgroup.
-func UserOwnsCurrentSystemdCgroup() (bool, error) {
- uid := os.Geteuid()
-
- cgroup2, err := IsCgroup2UnifiedMode()
- if err != nil {
- return false, err
- }
-
- f, err := os.Open("/proc/self/cgroup")
- if err != nil {
- return false, errors.Wrapf(err, "open file /proc/self/cgroup")
- }
- defer f.Close()
-
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- parts := strings.SplitN(line, ":", 3)
-
- if len(parts) < 3 {
- continue
- }
-
- var cgroupPath string
-
- if cgroup2 {
- cgroupPath = filepath.Join(cgroupRoot, parts[2])
- } else {
- if parts[1] != "name=systemd" {
- continue
- }
- cgroupPath = filepath.Join(cgroupRoot, "systemd", parts[2])
- }
-
- st, err := os.Stat(cgroupPath)
- if err != nil {
- return false, err
- }
- s := st.Sys()
- if s == nil {
- return false, fmt.Errorf("error stat cgroup path %s", cgroupPath)
- }
-
- if int(s.(*syscall.Stat_t).Uid) != uid {
- return false, nil
- }
- }
- if err := scanner.Err(); err != nil {
- return false, errors.Wrapf(err, "parsing file /proc/self/cgroup")
- }
- return true, nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go
deleted file mode 100644
index cd140fbf3..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build !linux
-
-package cgroups
-
-// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode.
-func IsCgroup2UnifiedMode() (bool, error) {
- return false, nil
-}
-
-// UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the
-// current cgroup.
-func UserOwnsCurrentSystemdCgroup() (bool, error) {
- return false, nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cpu.go b/vendor/github.com/containers/common/pkg/cgroups/cpu.go
deleted file mode 100644
index a43a76b22..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/cpu.go
+++ /dev/null
@@ -1,123 +0,0 @@
-package cgroups
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
-)
-
-type cpuHandler struct {
-}
-
-func getCPUHandler() *cpuHandler {
- return &cpuHandler{}
-}
-
-func cleanString(s string) string {
- return strings.Trim(s, "\n")
-}
-
-func readAcct(ctr *CgroupControl, name string) (uint64, error) {
- p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name)
- return readFileAsUint64(p)
-}
-
-func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) {
- var r []uint64
-
- p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name)
- data, err := ioutil.ReadFile(p)
- if err != nil {
- return nil, errors.Wrapf(err, "reading %s", p)
- }
- for _, s := range strings.Split(string(data), " ") {
- s = cleanString(s)
- if s == "" {
- break
- }
- v, err := strconv.ParseUint(s, 10, 0)
- if err != nil {
- return nil, errors.Wrapf(err, "parsing %s", s)
- }
- r = append(r, v)
- }
- return r, nil
-}
-
-// Apply set the specified constraints
-func (c *cpuHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
- if res.CPU == nil {
- return nil
- }
- return fmt.Errorf("cpu apply not implemented yet")
-}
-
-// Create the cgroup
-func (c *cpuHandler) Create(ctr *CgroupControl) (bool, error) {
- if ctr.cgroup2 {
- return false, nil
- }
- return ctr.createCgroupDirectory(CPU)
-}
-
-// Destroy the cgroup
-func (c *cpuHandler) Destroy(ctr *CgroupControl) error {
- return rmDirRecursively(ctr.getCgroupv1Path(CPU))
-}
-
-// Stat fills a metrics structure with usage stats for the controller
-func (c *cpuHandler) Stat(ctr *CgroupControl, m *Metrics) error {
- var err error
- usage := CPUUsage{}
- if ctr.cgroup2 {
- values, err := readCgroup2MapFile(ctr, "cpu.stat")
- if err != nil {
- return err
- }
- if val, found := values["usage_usec"]; found {
- usage.Total, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
- if err != nil {
- return err
- }
- usage.Kernel *= 1000
- }
- if val, found := values["system_usec"]; found {
- usage.Kernel, err = strconv.ParseUint(cleanString(val[0]), 10, 0)
- if err != nil {
- return err
- }
- usage.Total *= 1000
- }
- // FIXME: How to read usage.PerCPU?
- } else {
- usage.Total, err = readAcct(ctr, "cpuacct.usage")
- if err != nil {
- if !os.IsNotExist(errors.Cause(err)) {
- return err
- }
- usage.Total = 0
- }
- usage.Kernel, err = readAcct(ctr, "cpuacct.usage_sys")
- if err != nil {
- if !os.IsNotExist(errors.Cause(err)) {
- return err
- }
- usage.Kernel = 0
- }
- usage.PerCPU, err = readAcctList(ctr, "cpuacct.usage_percpu")
- if err != nil {
- if !os.IsNotExist(errors.Cause(err)) {
- return err
- }
- usage.PerCPU = nil
- }
- }
- m.CPU = CPUMetrics{Usage: usage}
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/cpuset.go b/vendor/github.com/containers/common/pkg/cgroups/cpuset.go
deleted file mode 100644
index 46d0484f2..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/cpuset.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package cgroups
-
-import (
- "fmt"
- "io/ioutil"
- "path/filepath"
- "strings"
-
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
-)
-
-type cpusetHandler struct {
-}
-
-func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) {
- if dir == cgroupRoot {
- return nil, fmt.Errorf("could not find parent to initialize cpuset %s", file)
- }
- path := filepath.Join(dir, file)
- parentPath := path
- if cgroupv2 {
- parentPath = fmt.Sprintf("%s.effective", parentPath)
- }
- data, err := ioutil.ReadFile(parentPath)
- if err != nil {
- return nil, errors.Wrapf(err, "open %s", path)
- }
- if len(strings.Trim(string(data), "\n")) != 0 {
- return data, nil
- }
- data, err = cpusetCopyFileFromParent(filepath.Dir(dir), file, cgroupv2)
- if err != nil {
- return nil, err
- }
- if err := ioutil.WriteFile(path, data, 0644); err != nil {
- return nil, errors.Wrapf(err, "write %s", path)
- }
- return data, nil
-}
-
-func cpusetCopyFromParent(path string, cgroupv2 bool) error {
- for _, file := range []string{"cpuset.cpus", "cpuset.mems"} {
- if _, err := cpusetCopyFileFromParent(path, file, cgroupv2); err != nil {
- return err
- }
- }
- return nil
-}
-
-func getCpusetHandler() *cpusetHandler {
- return &cpusetHandler{}
-}
-
-// Apply set the specified constraints
-func (c *cpusetHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
- if res.CPU == nil {
- return nil
- }
- return fmt.Errorf("cpuset apply not implemented yet")
-}
-
-// Create the cgroup
-func (c *cpusetHandler) Create(ctr *CgroupControl) (bool, error) {
- if ctr.cgroup2 {
- path := filepath.Join(cgroupRoot, ctr.path)
- return true, cpusetCopyFromParent(path, true)
- }
-
- created, err := ctr.createCgroupDirectory(CPUset)
- if !created || err != nil {
- return created, err
- }
- return true, cpusetCopyFromParent(ctr.getCgroupv1Path(CPUset), false)
-}
-
-// Destroy the cgroup
-func (c *cpusetHandler) Destroy(ctr *CgroupControl) error {
- return rmDirRecursively(ctr.getCgroupv1Path(CPUset))
-}
-
-// Stat fills a metrics structure with usage stats for the controller
-func (c *cpusetHandler) Stat(ctr *CgroupControl, m *Metrics) error {
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/memory.go b/vendor/github.com/containers/common/pkg/cgroups/memory.go
deleted file mode 100644
index b3991f7e3..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/memory.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package cgroups
-
-import (
- "fmt"
- "path/filepath"
-
- spec "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-type memHandler struct {
-}
-
-func getMemoryHandler() *memHandler {
- return &memHandler{}
-}
-
-// Apply set the specified constraints
-func (c *memHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
- if res.Memory == nil {
- return nil
- }
- return fmt.Errorf("memory apply not implemented yet")
-}
-
-// Create the cgroup
-func (c *memHandler) Create(ctr *CgroupControl) (bool, error) {
- if ctr.cgroup2 {
- return false, nil
- }
- return ctr.createCgroupDirectory(Memory)
-}
-
-// Destroy the cgroup
-func (c *memHandler) Destroy(ctr *CgroupControl) error {
- return rmDirRecursively(ctr.getCgroupv1Path(Memory))
-}
-
-// Stat fills a metrics structure with usage stats for the controller
-func (c *memHandler) Stat(ctr *CgroupControl, m *Metrics) error {
- var err error
- usage := MemoryUsage{}
-
- var memoryRoot string
- filenames := map[string]string{}
-
- if ctr.cgroup2 {
- memoryRoot = filepath.Join(cgroupRoot, ctr.path)
- filenames["usage"] = "memory.current"
- filenames["limit"] = "memory.max"
- } else {
- memoryRoot = ctr.getCgroupv1Path(Memory)
- filenames["usage"] = "memory.usage_in_bytes"
- filenames["limit"] = "memory.limit_in_bytes"
- }
- usage.Usage, err = readFileAsUint64(filepath.Join(memoryRoot, filenames["usage"]))
- if err != nil {
- return err
- }
- usage.Limit, err = readFileAsUint64(filepath.Join(memoryRoot, filenames["limit"]))
- if err != nil {
- return err
- }
-
- m.Memory = MemoryMetrics{Usage: usage}
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/pids.go b/vendor/github.com/containers/common/pkg/cgroups/pids.go
deleted file mode 100644
index 65b9b5b34..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/pids.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package cgroups
-
-import (
- "fmt"
- "io/ioutil"
- "path/filepath"
-
- spec "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-type pidHandler struct {
-}
-
-func getPidsHandler() *pidHandler {
- return &pidHandler{}
-}
-
-// Apply set the specified constraints
-func (c *pidHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error {
- if res.Pids == nil {
- return nil
- }
- var PIDRoot string
-
- if ctr.cgroup2 {
- PIDRoot = filepath.Join(cgroupRoot, ctr.path)
- } else {
- PIDRoot = ctr.getCgroupv1Path(Pids)
- }
-
- p := filepath.Join(PIDRoot, "pids.max")
- return ioutil.WriteFile(p, []byte(fmt.Sprintf("%d\n", res.Pids.Limit)), 0644)
-}
-
-// Create the cgroup
-func (c *pidHandler) Create(ctr *CgroupControl) (bool, error) {
- return ctr.createCgroupDirectory(Pids)
-}
-
-// Destroy the cgroup
-func (c *pidHandler) Destroy(ctr *CgroupControl) error {
- return rmDirRecursively(ctr.getCgroupv1Path(Pids))
-}
-
-// Stat fills a metrics structure with usage stats for the controller
-func (c *pidHandler) Stat(ctr *CgroupControl, m *Metrics) error {
- var PIDRoot string
-
- if ctr.cgroup2 {
- PIDRoot = filepath.Join(cgroupRoot, ctr.path)
- } else {
- PIDRoot = ctr.getCgroupv1Path(Pids)
- }
-
- current, err := readFileAsUint64(filepath.Join(PIDRoot, "pids.current"))
- if err != nil {
- return err
- }
-
- m.Pids = PidsMetrics{Current: current}
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd.go b/vendor/github.com/containers/common/pkg/cgroups/systemd.go
deleted file mode 100644
index b8e6db156..000000000
--- a/vendor/github.com/containers/common/pkg/cgroups/systemd.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package cgroups
-
-import (
- "fmt"
- "path/filepath"
- "strings"
-
- systemdDbus "github.com/coreos/go-systemd/dbus"
- "github.com/godbus/dbus"
-)
-
-func systemdCreate(path string, c *systemdDbus.Conn) error {
- slice, name := filepath.Split(path)
- slice = strings.TrimSuffix(slice, "/")
-
- var lastError error
- for i := 0; i < 2; i++ {
- properties := []systemdDbus.Property{
- systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)),
- systemdDbus.PropWants(slice),
- }
- pMap := map[string]bool{
- "DefaultDependencies": false,
- "MemoryAccounting": true,
- "CPUAccounting": true,
- "BlockIOAccounting": true,
- }
- if i == 0 {
- pMap["Delegate"] = true
- }
- for k, v := range pMap {
- p := systemdDbus.Property{
- Name: k,
- Value: dbus.MakeVariant(v),
- }
- properties = append(properties, p)
- }
-
- ch := make(chan string)
- _, err := c.StartTransientUnit(name, "replace", properties, ch)
- if err != nil {
- lastError = err
- continue
- }
- <-ch
- return nil
- }
- return lastError
-}
-
-/*
- systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that
- has the following license:
-
- Copyright The containerd Authors.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-func systemdDestroyConn(path string, c *systemdDbus.Conn) error {
- name := filepath.Base(path)
-
- ch := make(chan string)
- _, err := c.StopUnit(name, "replace", ch)
- if err != nil {
- return err
- }
- <-ch
- return nil
-}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
new file mode 100644
index 000000000..4b536b3a5
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -0,0 +1,885 @@
+package config
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+ "syscall"
+
+ "github.com/BurntSushi/toml"
+ "github.com/containers/common/pkg/capabilities"
+ "github.com/containers/common/pkg/unshare"
+ "github.com/containers/storage"
+ units "github.com/docker/go-units"
+ selinux "github.com/opencontainers/selinux/go-selinux"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ // DefaultContainersConfig holds the default containers config path
+ DefaultContainersConfig = "/usr/share/containers/containers.conf"
+ // OverrideContainersConfig holds the default config paths overridden by the root user
+ OverrideContainersConfig = "/etc/containers/containers.conf"
+ // UserOverrideContainersConfig holds the containers config path overridden by the rootless user
+ UserOverrideContainersConfig = ".config/containers/containers.conf"
+)
+
+// RuntimeStateStore is a constant indicating which state store implementation
+// should be used by libpod
+type RuntimeStateStore int
+
+const (
+ // InvalidStateStore is an invalid state store
+ InvalidStateStore RuntimeStateStore = iota
+ // InMemoryStateStore is an in-memory state that will not persist data
+ // on containers and pods between libpod instances or after system
+ // reboot
+ InMemoryStateStore RuntimeStateStore = iota
+ // SQLiteStateStore is a state backed by a SQLite database
+ // It is presently disabled
+ SQLiteStateStore RuntimeStateStore = iota
+ // BoltDBStateStore is a state backed by a BoltDB database
+ BoltDBStateStore RuntimeStateStore = iota
+)
+
+// Config contains configuration options for container tools
+type Config struct {
+ // Containers specify settings that configure how containers will run ont the system
+ Containers ContainersConfig `toml:"containers"`
+ // Libpod specifies how the container engine based on Libpod will run
+ Libpod LibpodConfig `toml:"libpod"`
+ // Network section defines the configuration of CNI Plugins
+ Network NetworkConfig `toml:"network"`
+}
+
+// ContainersConfig represents the "containers" TOML config table
+// containers global options for containers tools
+type ContainersConfig struct {
+
+ // Devices to add to all containers
+ Devices []string `toml:"devices"`
+
+ // Volumes to add to all containers
+ Volumes []string `toml:"volumes"`
+
+ // ApparmorProfile is the apparmor profile name which is used as the
+ // default for the runtime.
+ ApparmorProfile string `toml:"apparmor_profile"`
+
+ // Annotation to add to all containers
+ Annotations []string `toml:"annotations"`
+
+ // Default way to create a cgroup namespace for the container
+ CgroupNS string `toml:"cgroupns"`
+
+ // Capabilities to add to all containers.
+ DefaultCapabilities []string `toml:"default_capabilities"`
+
+ // Sysctls to add to all containers.
+ DefaultSysctls []string `toml:"default_sysctls"`
+
+ // DefaultUlimits specifies the default ulimits to apply to containers
+ DefaultUlimits []string `toml:"default_ulimits"`
+
+ // DefaultMountsFile is the path to the default mounts file for testing
+ DefaultMountsFile string `toml:"-"`
+
+ // DNSServers set default DNS servers.
+ DNSServers []string `toml:"dns_servers"`
+
+ // DNSOptions set default DNS options.
+ DNSOptions []string `toml:"dns_options"`
+
+ // DNSSearches set default DNS search domains.
+ DNSSearches []string `toml:"dns_searches"`
+
+ // EnableLabeling tells the container engines whether to use MAC
+ // Labeling to separate containers (SELinux)
+ EnableLabeling bool `toml:"label"`
+
+ // Env is the environment variable list for container process.
+ Env []string `toml:"env"`
+
+ // EnvHost Pass all host environment variables into the container.
+ EnvHost bool `toml:"env_host"`
+
+ // HTTPProxy is the proxy environment variable list to apply to container process
+ HTTPProxy bool `toml:"http_proxy"`
+
+ // Init tells container runtimes whether to run init inside the
+ // container that forwards signals and reaps processes.
+ Init bool `toml:"init"`
+
+ // InitPath is the path for init to run if the Init bool is enabled
+ InitPath string `toml:"init_path"`
+
+ // IPCNS way to to create a ipc namespace for the container
+ IPCNS string `toml:"ipcns"`
+
+ // LogDriver for the container. For example: k8s-file and journald
+ LogDriver string `toml:"log_driver"`
+
+ // LogSizeMax is the maximum number of bytes after which the log file
+ // will be truncated. It can be expressed as a human-friendly string
+ // that is parsed to bytes.
+ // Negative values indicate that the log file won't be truncated.
+ LogSizeMax int64 `toml:"log_size_max"`
+
+ // NetNS indicates how to create a network namespace for the container
+ NetNS string `toml:"netns"`
+
+ // NoHosts tells container engine whether to create its own /etc/hosts
+ NoHosts bool `toml:"no_hosts"`
+
+ // PidsLimit is the number of processes each container is restricted to
+ // by the cgroup process number controller.
+ PidsLimit int64 `toml:"pids_limit"`
+
+ // PidNS indicates how to create a pid namespace for the container
+ PidNS string `toml:"pidns"`
+
+ // SeccompProfile is the seccomp.json profile path which is used as the
+ // default for the runtime.
+ SeccompProfile string `toml:"seccomp_profile"`
+
+ // ShmSize holds the size of /dev/shm.
+ ShmSize string `toml:"shm_size"`
+
+ // SignaturePolicyPath is the path to a signature policy to use for
+ // validating images. If left empty, the containers/image default signature
+ // policy will be used.
+ SignaturePolicyPath string `toml:"_"`
+
+ // UTSNS indicates how to create a UTS namespace for the container
+ UTSNS string `toml:"utsns"`
+
+ // UserNS indicates how to create a User namespace for the container
+ UserNS string `toml:"userns"`
+
+ // UserNSSize how many UIDs to allocate for automatically created UserNS
+ UserNSSize int `toml:"userns_size"`
+}
+
+// LibpodConfig contains configuration options used to set up a libpod runtime
+type LibpodConfig struct {
+ // CGroupManager is the CGroup Manager to use Valid values are "cgroupfs"
+ // and "systemd".
+ CgroupManager string `toml:"cgroup_manager"`
+
+ // NOTE: when changing this struct, make sure to update (*Config).Merge().
+
+ // ConmonEnvVars are environment variables to pass to the Conmon binary
+ // when it is launched.
+ ConmonEnvVars []string `toml:"conmon_env_vars"`
+
+ // ConmonPath is the path to the Conmon binary used for managing containers.
+ // The first path pointing to a valid file will be used.
+ ConmonPath []string `toml:"conmon_path"`
+
+ //DetachKeys is the sequence of keys used to detach a container.
+ DetachKeys string `toml:"detach_keys"`
+
+ // EnablePortReservation determines whether libpod will reserve ports on the
+ // host when they are forwarded to containers. When enabled, when ports are
+ // forwarded to containers, they are held open by conmon as long as the
+ // container is running, ensuring that they cannot be reused by other
+ // programs on the host. However, this can cause significant memory usage if
+ // a container has many ports forwarded to it. Disabling this can save
+ // memory.
+ EnablePortReservation bool `toml:"enable_port_reservation"`
+
+ // EventsLogFilePath is where the events log is stored.
+ EventsLogFilePath string `toml:"events_logfile_path"`
+
+ // EventsLogger determines where events should be logged.
+ EventsLogger string `toml:"events_logger"`
+
+ // configuration files. When the same filename is present in in
+ // multiple directories, the file in the directory listed last in
+ // this slice takes precedence.
+ HooksDir []string `toml:"hooks_dir"`
+
+ // ImageDefaultTransport is the default transport method used to fetch
+ // images.
+ ImageDefaultTransport string `toml:"image_default_transport"`
+
+ // InfraCommand is the command run to start up a pod infra container.
+ InfraCommand string `toml:"infra_command"`
+
+ // InfraImage is the image a pod infra container will use to manage
+ // namespaces.
+ InfraImage string `toml:"infra_image"`
+
+ // InitPath is the path to the container-init binary.
+ InitPath string `toml:"init_path"`
+
+ // LockType is the type of locking to use.
+ LockType string `toml:"lock_type,omitempty"`
+
+ // Namespace is the libpod namespace to use. Namespaces are used to create
+ // scopes to separate containers and pods in the state. When namespace is
+ // set, libpod will only view containers and pods in the same namespace. All
+ // containers and pods created will default to the namespace set here. A
+ // namespace of "", the empty string, is equivalent to no namespace, and all
+ // containers and pods will be visible. The default namespace is "".
+ Namespace string `toml:"namespace,omitempty"`
+
+ // NetworkCmdPath is the path to the slirp4netns binary.
+ NetworkCmdPath string `toml:"network_cmd_path"`
+
+ // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime.
+ NoPivotRoot bool `toml:"no_pivot_root"`
+
+ // NumLocks is the number of locks to make available for containers and
+ // pods.
+ NumLocks uint32 `toml:"num_locks,omitempty"`
+
+ // OCIRuntime is the OCI runtime to use.
+ OCIRuntime string `toml:"runtime"`
+
+ // OCIRuntimes are the set of configured OCI runtimes (default is runc).
+ OCIRuntimes map[string][]string `toml:"runtimes"`
+
+ // RuntimeSupportsJSON is the list of the OCI runtimes that support
+ // --format=json.
+ RuntimeSupportsJSON []string `toml:"runtime_supports_json"`
+
+ // RuntimeSupportsNoCgroups is a list of OCI runtimes that support
+ // running containers without CGroups.
+ RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"`
+
+ // SetOptions contains a subset of config options. It's used to indicate if
+ // a given option has either been set by the user or by a parsed libpod
+ // configuration file. If not, the corresponding option might be
+ // overwritten by values from the database. This behavior guarantees
+ // backwards compat with older version of libpod and Podman.
+ SetOptions
+
+ // SDNotify tells container engine to allow containers to notify the host systemd of
+ // readiness using the SD_NOTIFY mechanism.
+ SDNotify bool
+
+ // StateType is the type of the backing state store. Avoid using multiple
+ // values for this with the same containers/storage configuration on the
+ // same system. Different state types do not interact, and each will see a
+ // separate set of containers, which may cause conflicts in
+ // containers/storage. As such this is not exposed via the config file.
+ StateType RuntimeStateStore `toml:"-"`
+
+ // StaticDir is the path to a persistent directory to store container
+ // files.
+ StaticDir string `toml:"static_dir"`
+
+ // StopTimeout is the number of seconds to wait for container to exit
+ // before sending kill signal.
+ StopTimeout uint `toml:"stop_timeout"`
+
+ // StorageConfig is the configuration used by containers/storage Not
+ // included in the on-disk config, use the dedicated containers/storage
+ // configuration file instead.
+ StorageConfig storage.StoreOptions `toml:"-"`
+
+ // TmpDir is the path to a temporary directory to store per-boot container
+ // files. Must be stored in a tmpfs.
+ TmpDir string `toml:"tmp_dir"`
+
+ // VolumePath is the default location that named volumes will be created
+ // under. This convention is followed by the default volume driver, but
+ // may not be by other drivers.
+ VolumePath string `toml:"volume_path"`
+}
+
+// SetOptions contains a subset of options in a Config. It's used to indicate if
+// a given option has either been set by the user or by a parsed libpod
+// configuration file. If not, the corresponding option might be overwritten by
+// values from the database. This behavior guarantees backwards compat with
+// older version of libpod and Podman.
+type SetOptions struct {
+ // StorageConfigRunRootSet indicates if the RunRoot has been explicitly set
+ // by the config or by the user. It's required to guarantee backwards
+ // compatibility with older versions of libpod for which we must query the
+ // database configuration. Not included in the on-disk config.
+ StorageConfigRunRootSet bool `toml:"-"`
+
+ // StorageConfigGraphRootSet indicates if the RunRoot has been explicitly
+ // set by the config or by the user. It's required to guarantee backwards
+ // compatibility with older versions of libpod for which we must query the
+ // database configuration. Not included in the on-disk config.
+ StorageConfigGraphRootSet bool `toml:"-"`
+
+ // StorageConfigGraphDriverNameSet indicates if the GraphDriverName has been
+ // explicitly set by the config or by the user. It's required to guarantee
+ // backwards compatibility with older versions of libpod for which we must
+ // query the database configuration. Not included in the on-disk config.
+ StorageConfigGraphDriverNameSet bool `toml:"-"`
+
+ // StaticDirSet indicates if the StaticDir has been explicitly set by the
+ // config or by the user. It's required to guarantee backwards compatibility
+ // with older versions of libpod for which we must query the database
+ // configuration. Not included in the on-disk config.
+ StaticDirSet bool `toml:"-"`
+
+ // VolumePathSet indicates if the VolumePath has been explicitly set by the
+ // config or by the user. It's required to guarantee backwards compatibility
+ // with older versions of libpod for which we must query the database
+ // configuration. Not included in the on-disk config.
+ VolumePathSet bool `toml:"-"`
+
+ // TmpDirSet indicates if the TmpDir has been explicitly set by the config
+ // or by the user. It's required to guarantee backwards compatibility with
+ // older versions of libpod for which we must query the database
+ // configuration. Not included in the on-disk config.
+ TmpDirSet bool `toml:"-"`
+}
+
+// NetworkConfig represents the "network" TOML config table
+type NetworkConfig struct {
+ // CNIPluginDirs is where CNI plugin binaries are stored.
+ CNIPluginDirs []string `toml:"cni_plugin_dirs"`
+
+ // DefaultNetwork is the network name of the default CNI network
+ // to attach pods to.
+ DefaultNetwork string `toml:"default_network,omitempty"`
+
+ // NetworkConfigDir is where CNI network configuration files are stored.
+ NetworkConfigDir string `toml:"network_config_dir"`
+}
+
+// NewConfig creates a new Config. It starts with an empty config and, if
+// specified, merges the config at `userConfigPath` path. Depending if we're
+// running as root or rootless, we then merge the system configuration followed
+// by merging the default config (hard-coded default in memory).
+// Note that the OCI runtime is hard-set to `crun` if we're running on a system
+// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This
+// might change in the future.
+func NewConfig(userConfigPath string) (*Config, error) {
+
+ // Generate the default config for the system
+ config, err := DefaultConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ // If the caller specified a config path to use, then we read this
+ // rather then using the system defaults.
+ if userConfigPath != "" {
+ var err error
+ // readConfigFromFile reads in container config in the specified
+ // file and then merge changes with the current default.
+ config, err = readConfigFromFile(userConfigPath, config)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath)
+ }
+ }
+
+ // Now, gather the system configs and merge them as needed.
+ configs, err := systemConfigs()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error finding config on system")
+ }
+ for _, path := range configs {
+ // Merge changes in later configs with the previous configs.
+ // Each config file that specified fields, will override the
+ // previous fields.
+ config, err := readConfigFromFile(path, config)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading system config %q", path)
+ }
+ logrus.Debugf("Merged system config %q: %v", path, config)
+ }
+
+ config.checkCgroupsAndAdjustConfig()
+ config.addCAPPrefix()
+
+ if err := config.Validate(); err != nil {
+ return nil, err
+ }
+
+ return config, nil
+}
+
+// readConfigFromFile reads the specified config file at `path` and attempts to
+// unmarshal its content into a Config. The config param specifies the previous
+// default config. If the path, only specifies a few fields in the Toml file
+// the defaults from the config parameter will be used for all other fields.
+func readConfigFromFile(path string, config *Config) (*Config, error) {
+ logrus.Debugf("Reading configuration file %q", path)
+ _, err := toml.DecodeFile(path, config)
+ if err != nil {
+ return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err)
+ }
+ if config.Libpod.VolumePath != "" {
+ config.Libpod.VolumePathSet = true
+ }
+ if config.Libpod.StaticDir != "" {
+ config.Libpod.StaticDirSet = true
+ }
+ if config.Libpod.TmpDir != "" {
+ config.Libpod.TmpDirSet = true
+ }
+
+ return config, err
+}
+
+// Returns the list of configuration files, if they exist in order of hierarchy.
+// The files are read in order and each new file can/will override previous
+// file settings.
+func systemConfigs() ([]string, error) {
+ configs := []string{}
+ path := os.Getenv("CONTAINERS_CONF")
+ if path != "" {
+ if _, err := os.Stat(path); err != nil {
+ return nil, errors.Wrap(err, "failed to stat of %s from CONTAINERS_CONF environment variable")
+ }
+ return append(configs, path), nil
+ }
+ if _, err := os.Stat(DefaultContainersConfig); err == nil {
+ configs = append(configs, DefaultContainersConfig)
+ }
+ if _, err := os.Stat(OverrideContainersConfig); err == nil {
+ configs = append(configs, OverrideContainersConfig)
+ }
+ if unshare.IsRootless() {
+ path, err := rootlessConfigPath()
+ if err != nil {
+ return nil, err
+ }
+ if _, err := os.Stat(path); err == nil {
+ configs = append(configs, path)
+ }
+ }
+ return configs, nil
+}
+
+// checkCgroupsAndAdjustConfig checks if we're running rootless with the systemd
+// cgroup manager. In case the user session isn't available, we're switching the
+// cgroup manager to cgroupfs. Note, this only applies to rootless.
+func (c *Config) checkCgroupsAndAdjustConfig() {
+ if !unshare.IsRootless() || c.Libpod.CgroupManager != SystemdCgroupsManager {
+ return
+ }
+
+ session := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
+ hasSession := session != ""
+ if hasSession && strings.HasPrefix(session, "unix:path=") {
+ _, err := os.Stat(strings.TrimPrefix(session, "unix:path="))
+ hasSession = err == nil
+ }
+
+ if !hasSession {
+ logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available")
+ logrus.Warningf("For using systemd, you may need to login using an user session")
+ logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", unshare.GetRootlessUID())
+ logrus.Warningf("Falling back to --cgroup-manager=cgroupfs")
+ c.Libpod.CgroupManager = CgroupfsCgroupsManager
+ }
+}
+
+func (c *Config) addCAPPrefix() {
+ toCAPPrefixed := func(cap string) string {
+ if !strings.HasPrefix(strings.ToLower(cap), "cap_") {
+ return "CAP_" + strings.ToUpper(cap)
+ }
+ return cap
+ }
+ for i, cap := range c.Containers.DefaultCapabilities {
+ c.Containers.DefaultCapabilities[i] = toCAPPrefixed(cap)
+ }
+}
+
+// Validate is the main entry point for library configuration validation.
+func (c *Config) Validate() error {
+
+ if err := c.Containers.Validate(); err != nil {
+ return errors.Wrapf(err, "containers config")
+ }
+
+ if !c.Containers.EnableLabeling {
+ selinux.SetDisabled()
+ }
+
+ return nil
+}
+
+// Validate is the main entry point for Libpod configuration validation
+// It returns an `error` on validation failure, otherwise
+// `nil`.
+func (c *LibpodConfig) Validate() error {
+ // Relative paths can cause nasty bugs, because core paths we use could
+ // shift between runs (or even parts of the program - the OCI runtime
+ // uses a different working directory than we do, for example.
+ if !filepath.IsAbs(c.StaticDir) {
+ return fmt.Errorf("static directory must be an absolute path - instead got %q", c.StaticDir)
+ }
+ if !filepath.IsAbs(c.TmpDir) {
+ return fmt.Errorf("temporary directory must be an absolute path - instead got %q", c.TmpDir)
+ }
+ if !filepath.IsAbs(c.VolumePath) {
+ return fmt.Errorf("volume path must be an absolute path - instead got %q", c.VolumePath)
+ }
+ return nil
+}
+
+// Validate is the main entry point for containers configuration validation
+// It returns an `error` on validation failure, otherwise
+// `nil`.
+func (c *ContainersConfig) Validate() error {
+ for _, u := range c.DefaultUlimits {
+ ul, err := units.ParseUlimit(u)
+ if err != nil {
+ return fmt.Errorf("unrecognized ulimit %s: %v", u, err)
+ }
+ _, err = ul.GetRlimit()
+ if err != nil {
+ return err
+ }
+ }
+
+ for _, d := range c.Devices {
+ _, _, _, err := Device(d)
+ if err != nil {
+ return err
+ }
+ }
+
+ if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize {
+ return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize)
+ }
+
+ if _, err := units.FromHumanSize(c.ShmSize); err != nil {
+ return fmt.Errorf("invalid --shm-size %s, %q", c.ShmSize, err)
+ }
+
+ return nil
+}
+
+// Validate is the main entry point for network configuration validation.
+// The parameter `onExecution` specifies if the validation should include
+// execution checks. It returns an `error` on validation failure, otherwise
+// `nil`.
+func (c *NetworkConfig) Validate() error {
+
+ if c.NetworkConfigDir != cniConfigDir {
+ err := isDirectory(c.NetworkConfigDir)
+ if err != nil {
+ return errors.Wrapf(err, "invalid network_config_dir: %s", c.NetworkConfigDir)
+ }
+ }
+
+ if stringsEq(c.CNIPluginDirs, cniBinDir) {
+ return nil
+ }
+
+ for _, pluginDir := range c.CNIPluginDirs {
+ if err := isDirectory(pluginDir); err == nil {
+ return nil
+ }
+ }
+
+ return errors.Errorf("invalid cni_plugin_dirs: %s", strings.Join(c.CNIPluginDirs, ","))
+}
+
+// DBConfig is a set of Libpod runtime configuration settings that are saved in
+// a State when it is first created, and can subsequently be retrieved.
+type DBConfig struct {
+ LibpodRoot string
+ LibpodTmp string
+ StorageRoot string
+ StorageTmp string
+ GraphDriver string
+ VolumePath string
+}
+
+// MergeDBConfig merges the configuration from the database.
+func (c *Config) MergeDBConfig(dbConfig *DBConfig) error {
+
+ if !c.Libpod.StorageConfigRunRootSet && dbConfig.StorageTmp != "" {
+ if c.Libpod.StorageConfig.RunRoot != dbConfig.StorageTmp &&
+ c.Libpod.StorageConfig.RunRoot != "" {
+ logrus.Debugf("Overriding run root %q with %q from database",
+ c.Libpod.StorageConfig.RunRoot, dbConfig.StorageTmp)
+ }
+ c.Libpod.StorageConfig.RunRoot = dbConfig.StorageTmp
+ }
+
+ if !c.Libpod.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" {
+ if c.Libpod.StorageConfig.GraphRoot != dbConfig.StorageRoot &&
+ c.Libpod.StorageConfig.GraphRoot != "" {
+ logrus.Debugf("Overriding graph root %q with %q from database",
+ c.Libpod.StorageConfig.GraphRoot, dbConfig.StorageRoot)
+ }
+ c.Libpod.StorageConfig.GraphRoot = dbConfig.StorageRoot
+ }
+
+ if !c.Libpod.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" {
+ if c.Libpod.StorageConfig.GraphDriverName != dbConfig.GraphDriver &&
+ c.Libpod.StorageConfig.GraphDriverName != "" {
+ logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
+ c.Libpod.StorageConfig.GraphDriverName, dbConfig.GraphDriver)
+ }
+ c.Libpod.StorageConfig.GraphDriverName = dbConfig.GraphDriver
+ }
+
+ if !c.Libpod.StaticDirSet && dbConfig.LibpodRoot != "" {
+ if c.Libpod.StaticDir != dbConfig.LibpodRoot && c.Libpod.StaticDir != "" {
+ logrus.Debugf("Overriding static dir %q with %q from database", c.Libpod.StaticDir, dbConfig.LibpodRoot)
+ }
+ c.Libpod.StaticDir = dbConfig.LibpodRoot
+ }
+
+ if !c.Libpod.TmpDirSet && dbConfig.LibpodTmp != "" {
+ if c.Libpod.TmpDir != dbConfig.LibpodTmp && c.Libpod.TmpDir != "" {
+ logrus.Debugf("Overriding tmp dir %q with %q from database", c.Libpod.TmpDir, dbConfig.LibpodTmp)
+ }
+ c.Libpod.TmpDir = dbConfig.LibpodTmp
+ c.Libpod.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log")
+ }
+
+ if !c.Libpod.VolumePathSet && dbConfig.VolumePath != "" {
+ if c.Libpod.VolumePath != dbConfig.VolumePath && c.Libpod.VolumePath != "" {
+ logrus.Debugf("Overriding volume path %q with %q from database", c.Libpod.VolumePath, dbConfig.VolumePath)
+ }
+ c.Libpod.VolumePath = dbConfig.VolumePath
+ }
+ return nil
+}
+
+// FindConmon iterates over (*Config).ConmonPath and returns the path
+// to first (version) matching conmon binary. If non is found, we try
+// to do a path lookup of "conmon".
+func (c *Config) FindConmon() (string, error) {
+ foundOutdatedConmon := false
+ for _, path := range c.Libpod.ConmonPath {
+ stat, err := os.Stat(path)
+ if err != nil {
+ continue
+ }
+ if stat.IsDir() {
+ continue
+ }
+ if err := probeConmon(path); err != nil {
+ logrus.Warnf("Conmon at %s invalid: %v", path, err)
+ foundOutdatedConmon = true
+ continue
+ }
+ logrus.Debugf("Using conmon: %q", path)
+ return path, nil
+ }
+
+ // Search the $PATH as last fallback
+ if path, err := exec.LookPath("conmon"); err == nil {
+ if err := probeConmon(path); err != nil {
+ logrus.Warnf("Conmon at %s is invalid: %v", path, err)
+ foundOutdatedConmon = true
+ } else {
+ logrus.Debugf("Using conmon from $PATH: %q", path)
+ return path, nil
+ }
+ }
+
+ if foundOutdatedConmon {
+ return "", errors.Wrapf(ErrConmonOutdated,
+ "please update to v%d.%d.%d or later",
+ _conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion)
+ }
+
+ return "", errors.Wrapf(ErrInvalidArg,
+ "could not find a working conmon binary (configured options: %v)",
+ c.Libpod.ConmonPath)
+}
+
+// GetDefaultEnv returns the environment variables for the container.
+// It will checn the HTTPProxy and HostEnv booleans and add the appropriate
+// environment variables to the container.
+func (c *Config) GetDefaultEnv() []string {
+ var env []string
+ if c.Containers.EnvHost {
+ env = append(env, os.Environ()...)
+ } else if c.Containers.HTTPProxy {
+ proxy := []string{"http_proxy", "https_proxy", "ftp_proxy", "no_proxy", "HTTP_PROXY", "HTTPS_PROXY", "FTP_PROXY", "NO_PROXY"}
+ for _, p := range proxy {
+ if val, ok := os.LookupEnv(p); ok {
+ env = append(env, fmt.Sprintf("%s=%s", p, val))
+ }
+ }
+ }
+ return append(env, c.Containers.Env...)
+}
+
+// Capabilities returns the capabilities parses the Add and Drop capability
+// list from the default capabiltiies for the container
+func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []string) []string {
+
+ userNotRoot := func(user string) bool {
+ if user == "" || user == "root" || user == "0" {
+ return false
+ }
+ return true
+ }
+
+ var caps []string
+ defaultCapabilities := c.Containers.DefaultCapabilities
+ if userNotRoot(user) {
+ defaultCapabilities = []string{}
+ }
+
+ mapCap := make(map[string]bool, len(defaultCapabilities))
+ for _, c := range addCapabilities {
+ if strings.ToLower(c) == "all" {
+ defaultCapabilities = capabilities.AllCapabilities()
+ addCapabilities = nil
+ break
+ }
+ }
+
+ for _, c := range append(defaultCapabilities, addCapabilities...) {
+ mapCap[c] = true
+ }
+ for _, c := range dropCapabilities {
+ if "all" == strings.ToLower(c) {
+ return caps
+ }
+ mapCap[c] = false
+ }
+ for cap, add := range mapCap {
+ if add {
+ caps = append(caps, cap)
+ }
+ }
+ return caps
+}
+
+// Device parses device mapping string to a src, dest & permissions string
+// Valid values for device looklike:
+// '/dev/sdc"
+// '/dev/sdc:/dev/xvdc"
+// '/dev/sdc:/dev/xvdc:rwm"
+// '/dev/sdc:rm"
+func Device(device string) (string, string, string, error) {
+ src := ""
+ dst := ""
+ permissions := "rwm"
+ split := strings.Split(device, ":")
+ switch len(split) {
+ case 3:
+ if !IsValidDeviceMode(split[2]) {
+ return "", "", "", fmt.Errorf("invalid device mode: %s", split[2])
+ }
+ permissions = split[2]
+ fallthrough
+ case 2:
+ if IsValidDeviceMode(split[1]) {
+ permissions = split[1]
+ } else {
+ if len(split[1]) == 0 || split[1][0] != '/' {
+ return "", "", "", fmt.Errorf("invalid device mode: %s", split[1])
+ }
+ dst = split[1]
+ }
+ fallthrough
+ case 1:
+ if !strings.HasPrefix(split[0], "/dev/") {
+ return "", "", "", fmt.Errorf("invalid device mode: %s", split[0])
+ }
+ src = split[0]
+ default:
+ return "", "", "", fmt.Errorf("invalid device specification: %s", device)
+ }
+
+ if dst == "" {
+ dst = src
+ }
+ return src, dst, permissions, nil
+}
+
+// IsValidDeviceMode checks if the mode for device is valid or not.
+// IsValid mode is a composition of r (read), w (write), and m (mknod).
+func IsValidDeviceMode(mode string) bool {
+ var legalDeviceMode = map[rune]bool{
+ 'r': true,
+ 'w': true,
+ 'm': true,
+ }
+ if mode == "" {
+ return false
+ }
+ for _, c := range mode {
+ if !legalDeviceMode[c] {
+ return false
+ }
+ legalDeviceMode[c] = false
+ }
+ return true
+}
+
+// isDirectory tests whether the given path exists and is a directory. It
+// follows symlinks.
+func isDirectory(path string) error {
+ info, err := os.Stat(path)
+ if err != nil {
+ return err
+ }
+
+ if !info.Mode().IsDir() {
+ // Return a PathError to be consistent with os.Stat().
+ return &os.PathError{
+ Op: "stat",
+ Path: path,
+ Err: syscall.ENOTDIR,
+ }
+ }
+
+ return nil
+}
+
+func rootlessConfigPath() (string, error) {
+ home, err := unshare.HomeDir()
+ if err != nil {
+ return "", err
+ }
+
+ return filepath.Join(home, UserOverrideContainersConfig), nil
+}
+
+func stringsEq(a, b []string) bool {
+
+ if len(a) != len(b) {
+ return false
+ }
+
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+var (
+ configOnce sync.Once
+ config *Config
+)
+
+// Default returns the default container config.
+// Configuration files will be read in the following files:
+// * /usr/share/containers/containers.conf
+// * /etc/containers/containers.conf
+// * $HOME/.config/containers/containers.conf # When run in rootless mode
+// Fields in latter files override defaults set in previous files and the
+// default config.
+// None of these files are required, and not all fields need to be specified
+// in each file, only the fields you want to override.
+// The system defaults container config files can be overwritten using the
+// CONTAINERS_CONF environment variable. This is usually done for testing.
+func Default() (*Config, error) {
+ var err error
+ configOnce.Do(func() {
+ config, err = NewConfig("")
+ })
+ return config, err
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config_linux.go b/vendor/github.com/containers/common/pkg/config/config_linux.go
new file mode 100644
index 000000000..17b862967
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/config_linux.go
@@ -0,0 +1,7 @@
+package config
+
+import selinux "github.com/opencontainers/selinux/go-selinux"
+
+func selinuxEnabled() bool {
+ return selinux.GetEnabled()
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config_unix.go b/vendor/github.com/containers/common/pkg/config/config_unix.go
new file mode 100644
index 000000000..f270f2e95
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/config_unix.go
@@ -0,0 +1,15 @@
+// +build !windows
+
+package config
+
+// Defaults for linux/unix if none are specified
+const (
+ cniConfigDir = "/etc/cni/net.d/"
+)
+
+var cniBinDir = []string{
+ "/usr/libexec/cni",
+ "/usr/lib/cni",
+ "/usr/local/lib/cni",
+ "/opt/cni/bin",
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config_unsupported.go b/vendor/github.com/containers/common/pkg/config/config_unsupported.go
new file mode 100644
index 000000000..6563fd317
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/config_unsupported.go
@@ -0,0 +1,7 @@
+// +build !linux
+
+package config
+
+func selinuxEnabled() bool {
+ return false
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config_windows.go b/vendor/github.com/containers/common/pkg/config/config_windows.go
new file mode 100644
index 000000000..f6a6512a1
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/config_windows.go
@@ -0,0 +1,10 @@
+// +build windows
+
+package config
+
+// Defaults for linux/unix if none are specified
+const (
+ cniConfigDir = "C:\\cni\\etc\\net.d\\"
+)
+
+var cniBinDir = []string{"C:\\cni\\bin\\"}
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
new file mode 100644
index 000000000..91106b576
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -0,0 +1,375 @@
+# The containers configuration file specifies all of the available configuration
+# command-line options/flags for container runtime tools like Podman & Buildah,
+# but in a TOML format that can be easily modified and versioned.
+
+# Please refer to containers.conf(5) for details of all configuration options.
+# Not all container tools implement all of the options.
+# All of the options have hard coded defaults and these options will override
+# the built in defaults. Users can then override these options via the command
+# line. Container engines will read containers.conf files in up to three
+# locations in the following order:
+# 1. /usr/share/containers/containers.conf
+# 2. /etc/containers/containers.conf
+# 3. $HOME/.config/containers/containers.conf (Rootless containers ONLY)
+# Items specified in the latter containers.conf, if they exist, override the
+# previous containers.conf settings, or the default settings.
+
+[containers]
+
+# List of devices. Specified as
+# "<device-on-host>:<device-on-container>:<permissions>", for example:
+# "/dev/sdc:/dev/xvdc:rwm".
+# If it is empty or commented out, only the default devices will be used
+#
+# devices = []
+
+# List of volumes. Specified as
+# "<directory-on-host>:<directory-in-container>:<options>", for example:
+# "/db:/var/lib/db:ro".
+# If it is empty or commented out, no volumes will be added
+#
+# volumes = []
+
+# Used to change the name of the default AppArmor profile of container engines.
+#
+# apparmor_profile = "container-default"
+
+# List of annotation. Specified as
+# "key=value"
+# If it is empty or commented out, no annotations will be added
+#
+# annotations = []
+
+# Default way to to create a cgroup namespace for the container
+# Options are:
+# `private` Create private Cgroup Namespace for the container.
+# `host` Share host Cgroup Namespace with the container.
+#
+# cgroupns = "private"
+
+# List of default capabilities for containers. If it is empty or commented out,
+# the default capabilities defined in the container engine will be added.
+#
+# default_capabilities = [
+# "AUDIT_WRITE",
+# "CHOWN",
+# "DAC_OVERRIDE",
+# "FOWNER",
+# "FSETID",
+# "KILL",
+# "MKNOD",
+# "NET_BIND_SERVICE",
+# "NET_RAW",
+# "SETGID",
+# "SETPCAP",
+# "SETUID",
+# "SYS_CHROOT",
+# ]
+
+# A list of sysctls to be set in containers by default,
+# specified as "name=value",
+# for example:"net.ipv4.ping_group_range = 0 1000".
+#
+# default_sysctls = [
+# "net.ipv4.ping_group_range=0 1000",
+# ]
+
+# A list of ulimits to be set in containers by default, specified as
+# "<ulimit name>=<soft limit>:<hard limit>", for example:
+# "nofile=1024:2048"
+# See setrlimit(2) for a list of resource names.
+# Any limit not specified here will be inherited from the process launching the
+# container engine.
+# Ulimits has limits for non privileged container engines.
+#
+# default_ulimits = [
+# “nofile”=”1280:2560”,
+# ]
+
+# List of default DNS options to be added to /etc/resolv.conf inside of the container.
+#
+# dns_options = []
+
+# List of default DNS search domains to be added to /etc/resolv.conf inside of the container.
+#
+# dns_searches = []
+
+# Set default DNS servers.
+# This option can be used to override the DNS configuration passed to the
+# container. The special value “none” can be specified to disable creation of
+# /etc/resolv.conf in the container.
+# The /etc/resolv.conf file in the image will be used without changes.
+#
+# dns_servers = []
+
+# Environment variable list for the conmon process; used for passing necessary
+# environment variables to conmon or the runtime.
+#
+# env = [
+# "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+# ]
+
+# Pass all host environment variables into the container.
+#
+# env_host = false
+
+# Path to OCI hooks directories for automatically executed hooks.
+#
+# hooks_dir = [
+# “/usr/share/containers/oci/hooks.d”,
+# ]
+
+# Default proxy environment variables passed into the container.
+# The environment variables passed in include:
+# http_proxy, https_proxy, ftp_proxy, no_proxy, and the upper case versions of
+# these. This option is needed when host system uses a proxy but container
+# should not use proxy. Proxy environment variables specified for the container
+# in any other way will override the values passed from the host.
+#
+# http_proxy = true
+
+# Run an init inside the container that forwards signals and reaps processes.
+#
+# init = false
+
+# Container init binary, if init=true, this is the init binary to be used for containers.
+#
+# init_path = "/usr/libexec/podman/catatonit"
+
+# Default way to to create an IPC namespace (POSIX SysV IPC) for the container
+# Options are:
+# `private` Create private IPC Namespace for the container.
+# `host` Share host IPC Namespace with the container.
+#
+# ipcns = "private"
+
+# container engines use container separation using MAC(SELinux) labeling.
+# Flag is ignored on label disabled systems.
+#
+# label = true
+
+# Logging driver for the container. Available options: k8s-file and journald.
+#
+# log_driver = "k8s-file"
+
+# Maximum size allowed for the container log file. Negative numbers indicate
+# that no size limit is imposed. If positive, it must be >= 8192 to match or
+# exceed conmon's read buffer. The file is truncated and re-opened so the
+# limit is never exceeded.
+#
+# log_size_max = -1
+
+# Default way to to create a Network namespace for the container
+# Options are:
+# `private` Create private Network Namespace for the container.
+# `host` Share host Network Namespace with the container.
+# `none` Containers do not use the network
+#
+# netns = "private"
+
+# Create /etc/hosts for the container. By default, container engines manage
+# /etc/hosts, automatically adding the container's own IP address.
+#
+# no_hosts = false
+
+# Maximum number of processes allowed in a container.
+#
+# pids_limit = 2048
+
+# Default way to to create a PID namespace for the container
+# Options are:
+# `private` Create private PID Namespace for the container.
+# `host` Share host PID Namespace with the container.
+#
+# pidns = "private"
+
+# Path to the seccomp.json profile which is used as the default seccomp profile
+# for the runtime.
+#
+# seccomp_profile = "/usr/share/containers/seccomp.json"
+
+# Size of /dev/shm. Specified as <number><unit>.
+# Unit is optional, values:
+# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes).
+# If the unit is omitted, the system uses bytes.
+#
+# shm_size = "65536k"
+
+# Default way to to create a UTS namespace for the container
+# Options are:
+# `private` Create private UTS Namespace for the container.
+# `host` Share host UTS Namespace with the container.
+#
+# utsns = "private"
+
+# Default way to to create a User namespace for the container
+# Options are:
+# `auto` Create unique User Namespace for the container.
+# `host` Share host User Namespace with the container.
+#
+# userns = "host"
+
+# Number of UIDs to allocate for the automatic container creation.
+# UIDs are allocated from the “container” UIDs listed in
+# /etc/subuid & /etc/subgid
+#
+# userns_size=65536
+
+# The network table contains settings pertaining to the management of
+# CNI plugins.
+
+[network]
+
+# Path to directory where CNI plugin binaries are located.
+#
+# cni_plugin_dirs = ["/usr/libexec/cni"]
+
+# Path to the directory where CNI configuration files are located.
+#
+# network_config_dir = "/etc/cni/net.d/"
+
+[libpod]
+
+# Cgroup management implementation used for the runtime.
+# Valid options “systemd” or “cgroupfs”
+#
+# cgroup_manager = "systemd"
+
+# Environment variables to pass into conmon
+#
+# conmon_env_vars = [
+# "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+# ]
+
+# Paths to look for the conmon container manager binary
+#
+# conmon_path = [
+# "/usr/libexec/podman/conmon",
+# "/usr/local/libexec/podman/conmon",
+# "/usr/local/lib/podman/conmon",
+# "/usr/bin/conmon",
+# "/usr/sbin/conmon",
+# "/usr/local/bin/conmon",
+# "/usr/local/sbin/conmon"
+# ]
+
+# Specify the keys sequence used to detach a container.
+# Format is a single character [a-Z] or a comma separated sequence of
+# `ctrl-<value>`, where `<value>` is one of:
+# `a-z`, `@`, `^`, `[`, `\`, `]`, `^` or `_`
+#
+# detach_keys = "ctrl-p,ctrl-q"
+
+# Determines whether libpod will reserve ports on the host when they are
+# forwarded to containers. When enabled, when ports are forwarded to containers,
+# ports are held open by as long as the container is running, ensuring that
+# they cannot be reused by other programs on the host. However, this can cause
+# significant memory usage if a container has many ports forwarded to it.
+# Disabling this can save memory.
+#
+# enable_port_reservation = true
+
+# Selects which logging mechanism to use for container engine events.
+# Valid values are `journald`, `file` and `none`.
+#
+# events_logger = "journald"
+
+# Default transport method for pulling and pushing for images
+#
+# image_default_transport = "docker://"
+
+# Default command to run the infra container
+#
+# infra_command = "/pause"
+
+# Infra (pause) container image name for pod infra containers. When running a
+# pod, we start a `pause` process in a container to hold open the namespaces
+# associated with the pod. This container does nothing other then sleep,
+# reserving the pods resources for the lifetime of the pod.
+#
+# infra_image = "k8s.gcr.io/pause:3.1"
+
+# Specify the locking mechanism to use; valid values are "shm" and "file".
+# Change the default only if you are sure of what you are doing, in general
+# "file" is useful only on platforms where cgo is not available for using the
+# faster "shm" lock type. You may need to run "podman system renumber" after
+# you change the lock type.
+#
+# lock_type** = "shm"
+
+# Default libpod namespace
+# If libpod is joined to a namespace, it will see only containers and pods
+# that were created in the same namespace, and will create new containers and
+# pods in that namespace.
+# The default namespace is "", which corresponds to no namespace. When no
+# namespace is set, all containers and pods are visible.
+#
+# namespace = ""
+
+# Whether to use chroot instead of pivot_root in the runtime
+#
+# no_pivot_root = false
+
+# Number of locks available for containers and pods.
+# If this is changed, a lock renumber must be performed (e.g. with the
+# 'podman system renumber' command).
+#
+# num_locks = 2048
+
+# Directory for persistent libpod files (database, etc)
+# By default, this will be configured relative to where the containers/storage
+# stores containers
+# Uncomment to change location from this default
+#
+# static_dir = "/var/lib/containers/storage/libpod"
+
+# Directory for temporary files. Must be tmpfs (wiped after reboot)
+#
+# tmp_dir = "/var/run/libpod"
+
+# Directory for libpod named volumes.
+# By default, this will be configured relative to where containers/storage
+# stores containers.
+# Uncomment to change location from this default.
+#
+# volume_path = "/var/lib/containers/storage/volumes"
+
+# Default OCI runtime
+#
+# runtime = "runc"
+
+# List of the OCI runtimes that support --format=json. When json is supported
+# libpod will use it for reporting nicer errors.
+#
+# runtime_supports_json = ["crun", "runc"]
+
+# Paths to look for a valid OCI runtime (runc, runv, etc)
+[libpod.runtimes]
+# runc = [
+# "/usr/bin/runc",
+# "/usr/sbin/runc",
+# "/usr/local/bin/runc",
+# "/usr/local/sbin/runc",
+# "/sbin/runc",
+# "/bin/runc",
+# "/usr/lib/cri-o-runc/sbin/runc",
+# ]
+
+# crun = [
+# "/usr/bin/crun",
+# "/usr/sbin/crun",
+# "/usr/local/bin/crun",
+# "/usr/local/sbin/crun",
+# "/sbin/crun",
+# "/bin/crun",
+# "/run/current-system/sw/bin/crun",
+# ]
+
+# Number of seconds to wait for container to exit before sending kill signal.
+#stop_timeout = 10
+
+# The [libpod.runtimes] table MUST be the last entry in this file.
+# (Unless another table is added)
+# TOML does not provide a way to end a table other than a further table being
+# defined, so every key hereafter will be part of [runtimes] and not the main
+# config.
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
new file mode 100644
index 000000000..6b83d7703
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -0,0 +1,346 @@
+package config
+
+import (
+ "bytes"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strconv"
+
+ "github.com/containers/common/pkg/unshare"
+ "github.com/containers/storage"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ // _conmonMinMajorVersion is the major version required for conmon.
+ _conmonMinMajorVersion = 2
+
+ // _conmonMinMinorVersion is the minor version required for conmon.
+ _conmonMinMinorVersion = 0
+
+ // _conmonMinPatchVersion is the sub-minor version required for conmon.
+ _conmonMinPatchVersion = 1
+
+ // _conmonVersionFormatErr is used when the expected versio-format of conmon
+ // has changed.
+ _conmonVersionFormatErr = "conmon version changed format"
+
+ // _defaultGraphRoot points to the default path of the graph root.
+ _defaultGraphRoot = "/var/lib/containers/storage"
+
+ // _defaultTransport is a prefix that we apply to an image name to check
+ // docker hub first for the image.
+ _defaultTransport = "docker://"
+)
+
+var (
+ // DefaultInitPath is the default path to the container-init binary
+ DefaultInitPath = "/usr/libexec/podman/catatonit"
+ // DefaultInfraImage to use for infra container
+ DefaultInfraImage = "k8s.gcr.io/pause:3.1"
+ // DefaultInfraCommand to be run in an infra container
+ DefaultInfraCommand = "/pause"
+ // DefaultRootlessSHMLockPath is the default path for rootless SHM locks
+ DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
+ // DefaultDetachKeys is the default keys sequence for detaching a
+ // container
+ DefaultDetachKeys = "ctrl-p,ctrl-q"
+)
+
+var (
+ // ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
+ // is out of date for the current podman version
+ ErrConmonOutdated = errors.New("outdated conmon version")
+ // ErrInvalidArg indicates that an invalid argument was passed
+ ErrInvalidArg = errors.New("invalid argument")
+ // DefaultHooksDirs defines the default hooks directory
+ DefaultHooksDirs = []string{"/usr/share/containers/oci/hooks.d"}
+ // DefaultCapabilities for the default_capabilities option in the containers.conf file
+ DefaultCapabilities = []string{
+ "CAP_AUDIT_WRITE",
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FOWNER",
+ "CAP_FSETID",
+ "CAP_KILL",
+ "CAP_MKNOD",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_NET_RAW",
+ "CAP_SETFCAP",
+ "CAP_SETGID",
+ "CAP_SETPCAP",
+ "CAP_SETUID",
+ "CAP_SYS_CHROOT",
+ }
+)
+
+const (
+ // EtcDir is the sysconfdir where podman should look for system config files.
+ // It can be overridden at build time.
+ _etcDir = "/etc"
+ // InstallPrefix is the prefix where podman will be installed.
+ // It can be overridden at build time.
+ _installPrefix = "/usr"
+ // CgroupfsCgroupsManager represents cgroupfs native cgroup manager
+ CgroupfsCgroupsManager = "cgroupfs"
+ // DefaultApparmorProfile specifies the default apparmor profile for the container.
+ DefaultApparmorProfile = "container-default"
+ // SystemdCgroupsManager represents systemd native cgroup manager
+ SystemdCgroupsManager = "systemd"
+ // DefaultLogDriver is the default type of log files
+ DefaultLogDriver = "k8s-file"
+ // DefaultLogSizeMax is the default value for the maximum log size
+ // allowed for a container. Negative values mean that no limit is imposed.
+ DefaultLogSizeMax = -1
+ // DefaultPidsLimit is the default value for maximum number of processes
+ // allowed inside a container
+ DefaultPidsLimit = 2048
+ // DefaultRootlessSignaturePolicyPath is the default value for the
+ // rootless policy.json file.
+ DefaultRootlessSignaturePolicyPath = ".config/containers/policy.json"
+ // DefaultShmSize default value
+ DefaultShmSize = "65536k"
+ // DefaultUserNSSize default value
+ DefaultUserNSSize = 65536
+ // OCIBufSize limits maximum LogSizeMax
+ OCIBufSize = 8192
+ // SeccompOverridePath if this exists it overrides the default seccomp path.
+ SeccompOverridePath = _etcDir + "/containers/seccomp.json"
+ // SeccompDefaultPath defines the default seccomp path.
+ SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json"
+)
+
+// DefaultConfig defines the default values from containers.conf
+func DefaultConfig() (*Config, error) {
+
+ defaultLibpodConfig, err := defaultConfigFromMemory()
+ if err != nil {
+ return nil, err
+ }
+
+ var signaturePolicyPath string
+ netns := "bridge"
+ if unshare.IsRootless() {
+ home, err := unshare.HomeDir()
+ if err != nil {
+ return nil, err
+ }
+ sigPath := filepath.Join(home, DefaultRootlessSignaturePolicyPath)
+ if _, err := os.Stat(sigPath); err == nil {
+ signaturePolicyPath = sigPath
+ }
+ netns = "slirp4netns"
+ }
+
+ return &Config{
+ Containers: ContainersConfig{
+ Devices: []string{},
+ Volumes: []string{},
+ Annotations: []string{},
+ ApparmorProfile: DefaultApparmorProfile,
+ CgroupNS: "private",
+ DefaultCapabilities: DefaultCapabilities,
+ DefaultSysctls: []string{},
+ DefaultUlimits: getDefaultProcessLimits(),
+ DNSServers: []string{},
+ DNSOptions: []string{},
+ DNSSearches: []string{},
+ EnableLabeling: selinuxEnabled(),
+ Env: []string{
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ },
+ EnvHost: false,
+ HTTPProxy: false,
+ Init: false,
+ InitPath: "",
+ IPCNS: "private",
+ LogDriver: DefaultLogDriver,
+ LogSizeMax: DefaultLogSizeMax,
+ NetNS: netns,
+ NoHosts: false,
+ PidsLimit: DefaultPidsLimit,
+ PidNS: "private",
+ SeccompProfile: SeccompDefaultPath,
+ ShmSize: DefaultShmSize,
+ SignaturePolicyPath: signaturePolicyPath,
+ UTSNS: "private",
+ UserNS: "private",
+ UserNSSize: DefaultUserNSSize,
+ },
+ Network: NetworkConfig{
+ DefaultNetwork: "podman",
+ NetworkConfigDir: cniConfigDir,
+ CNIPluginDirs: cniBinDir,
+ },
+ Libpod: *defaultLibpodConfig,
+ }, nil
+}
+
+// defaultConfigFromMemory returns a default libpod configuration. Note that the
+// config is different for root and rootless. It also parses the storage.conf.
+func defaultConfigFromMemory() (*LibpodConfig, error) {
+ c := new(LibpodConfig)
+ tmp, err := defaultTmpDir()
+ if err != nil {
+ return nil, err
+ }
+ c.TmpDir = tmp
+
+ c.EventsLogFilePath = filepath.Join(c.TmpDir, "events", "events.log")
+
+ storeOpts, err := storage.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
+ if err != nil {
+ return nil, err
+ }
+ if storeOpts.GraphRoot == "" {
+ logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot)
+ storeOpts.GraphRoot = _defaultGraphRoot
+ }
+ c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod")
+ c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes")
+ c.StorageConfig = storeOpts
+
+ c.HooksDir = DefaultHooksDirs
+ c.ImageDefaultTransport = _defaultTransport
+ c.StateType = BoltDBStateStore
+
+ c.OCIRuntime = "runc"
+ // If we're running on cgroups v2, default to using crun.
+ if onCgroupsv2, _ := isCgroup2UnifiedMode(); onCgroupsv2 {
+ c.OCIRuntime = "crun"
+ }
+ c.CgroupManager = SystemdCgroupsManager
+ c.StopTimeout = uint(10)
+
+ c.OCIRuntimes = map[string][]string{
+ "runc": {
+ "/usr/bin/runc",
+ "/usr/sbin/runc",
+ "/usr/local/bin/runc",
+ "/usr/local/sbin/runc",
+ "/sbin/runc",
+ "/bin/runc",
+ "/usr/lib/cri-o-runc/sbin/runc",
+ "/run/current-system/sw/bin/runc",
+ },
+ "crun": {
+ "/usr/bin/crun",
+ "/usr/sbin/crun",
+ "/usr/local/bin/crun",
+ "/usr/local/sbin/crun",
+ "/sbin/crun",
+ "/bin/crun",
+ "/run/current-system/sw/bin/crun",
+ },
+ }
+ c.ConmonEnvVars = []string{
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ }
+ c.ConmonPath = []string{
+ "/usr/libexec/podman/conmon",
+ "/usr/local/libexec/podman/conmon",
+ "/usr/local/lib/podman/conmon",
+ "/usr/bin/conmon",
+ "/usr/sbin/conmon",
+ "/usr/local/bin/conmon",
+ "/usr/local/sbin/conmon",
+ "/run/current-system/sw/bin/conmon",
+ }
+ c.RuntimeSupportsJSON = []string{
+ "crun",
+ "runc",
+ }
+ c.RuntimeSupportsNoCgroups = []string{"crun"}
+ c.InitPath = DefaultInitPath
+ c.NoPivotRoot = false
+
+ c.InfraCommand = DefaultInfraCommand
+ c.InfraImage = DefaultInfraImage
+ c.EnablePortReservation = true
+ c.NumLocks = 2048
+ c.EventsLogger = "journald"
+ c.DetachKeys = DefaultDetachKeys
+ c.SDNotify = false
+ // TODO - ideally we should expose a `type LockType string` along with
+ // constants.
+ c.LockType = "shm"
+
+ return c, nil
+}
+
+func defaultTmpDir() (string, error) {
+ if !unshare.IsRootless() {
+ return "/var/run/libpod", nil
+ }
+
+ runtimeDir, err := getRuntimeDir()
+ if err != nil {
+ return "", err
+ }
+ libpodRuntimeDir := filepath.Join(runtimeDir, "libpod")
+
+ if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
+ if !os.IsExist(err) {
+ return "", errors.Wrapf(err, "cannot mkdir %s", libpodRuntimeDir)
+ } else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
+ // The directory already exist, just set the sticky bit
+ return "", errors.Wrapf(err, "could not set sticky bit on %s", libpodRuntimeDir)
+ }
+ }
+ return filepath.Join(libpodRuntimeDir, "tmp"), nil
+}
+
+// probeConmon calls conmon --version and verifies it is a new enough version for
+// the runtime expectations the container engine currently has.
+func probeConmon(conmonBinary string) error {
+ cmd := exec.Command(conmonBinary, "--version")
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ err := cmd.Run()
+ if err != nil {
+ return err
+ }
+ r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`)
+
+ matches := r.FindStringSubmatch(out.String())
+ if len(matches) != 4 {
+ return errors.Wrap(err, _conmonVersionFormatErr)
+ }
+ major, err := strconv.Atoi(matches[1])
+ if err != nil {
+ return errors.Wrap(err, _conmonVersionFormatErr)
+ }
+ if major < _conmonMinMajorVersion {
+ return ErrConmonOutdated
+ }
+ if major > _conmonMinMajorVersion {
+ return nil
+ }
+
+ minor, err := strconv.Atoi(matches[2])
+ if err != nil {
+ return errors.Wrap(err, _conmonVersionFormatErr)
+ }
+ if minor < _conmonMinMinorVersion {
+ return ErrConmonOutdated
+ }
+ if minor > _conmonMinMinorVersion {
+ return nil
+ }
+
+ patch, err := strconv.Atoi(matches[3])
+ if err != nil {
+ return errors.Wrap(err, _conmonVersionFormatErr)
+ }
+ if patch < _conmonMinPatchVersion {
+ return ErrConmonOutdated
+ }
+ if patch > _conmonMinPatchVersion {
+ return nil
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go
new file mode 100644
index 000000000..43ef5da78
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/default_linux.go
@@ -0,0 +1,55 @@
+package config
+
+import (
+ "fmt"
+ "io/ioutil"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
+func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
+ cgroupRoot := "/sys/fs/cgroup"
+
+ var st syscall.Statfs_t
+ if err := syscall.Statfs(cgroupRoot, &st); err != nil {
+ isUnified, isUnifiedErr = false, err
+ } else {
+ isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil
+ }
+ return
+}
+
+const (
+ oldMaxSize = uint64(1048576)
+)
+
+// getDefaultProcessLimits returns the nproc for the current process in ulimits format
+// Note that nfile sometimes cannot be set to unlimited, and the limit is hardcoded
+// to (oldMaxSize) 1048576 (2^20), see: http://stackoverflow.com/a/1213069/1811501
+// In rootless containers this will fail, and the process will just use its current limits
+func getDefaultProcessLimits() []string {
+ rlim := unix.Rlimit{Cur: oldMaxSize, Max: oldMaxSize}
+ oldrlim := rlim
+ // Attempt to set file limit and process limit to pid_max in OS
+ dat, err := ioutil.ReadFile("/proc/sys/kernel/pid_max")
+ if err == nil {
+ val := strings.TrimSuffix(string(dat), "\n")
+ max, err := strconv.ParseUint(val, 10, 64)
+ if err == nil {
+ rlim = unix.Rlimit{Cur: uint64(max), Max: uint64(max)}
+ }
+ }
+ defaultLimits := []string{}
+ if err := unix.Setrlimit(unix.RLIMIT_NPROC, &rlim); err == nil {
+ defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", rlim.Cur, rlim.Max))
+ } else {
+ if err := unix.Setrlimit(unix.RLIMIT_NPROC, &oldrlim); err == nil {
+ defaultLimits = append(defaultLimits, fmt.Sprintf("nproc=%d:%d", oldrlim.Cur, oldrlim.Max))
+ }
+ }
+ return defaultLimits
+}
diff --git a/vendor/github.com/containers/common/pkg/config/default_unsupported.go b/vendor/github.com/containers/common/pkg/config/default_unsupported.go
new file mode 100644
index 000000000..1ae1dd12c
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/default_unsupported.go
@@ -0,0 +1,13 @@
+// +build !linux
+
+package config
+
+// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
+func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
+ return false, nil
+}
+
+// getDefaultProcessLimits returns the nofile and nproc for the current process in ulimits format
+func getDefaultProcessLimits() []string {
+ return []string{}
+}
diff --git a/vendor/github.com/containers/common/pkg/config/util_supported.go b/vendor/github.com/containers/common/pkg/config/util_supported.go
new file mode 100644
index 000000000..101952f1d
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/util_supported.go
@@ -0,0 +1,69 @@
+// +build linux darwin
+
+package config
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "sync"
+ "syscall"
+
+ "github.com/containers/common/pkg/unshare"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ rootlessRuntimeDirOnce sync.Once
+ rootlessRuntimeDir string
+)
+
+// getRuntimeDir returns the runtime directory
+func getRuntimeDir() (string, error) {
+ var rootlessRuntimeDirError error
+
+ rootlessRuntimeDirOnce.Do(func() {
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+ uid := fmt.Sprintf("%d", unshare.GetRootlessUID())
+ if runtimeDir == "" {
+ tmpDir := filepath.Join("/run", "user", uid)
+ if err := os.MkdirAll(tmpDir, 0700); err != nil {
+ logrus.Debugf("unable to make temp dir %s", tmpDir)
+ }
+ st, err := os.Stat(tmpDir)
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
+ runtimeDir = tmpDir
+ }
+ }
+ if runtimeDir == "" {
+ tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid))
+ if err := os.MkdirAll(tmpDir, 0700); err != nil {
+ logrus.Debugf("unable to make temp dir %s", tmpDir)
+ }
+ st, err := os.Stat(tmpDir)
+ if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
+ runtimeDir = tmpDir
+ }
+ }
+ if runtimeDir == "" {
+ home := os.Getenv("HOME")
+ if home == "" {
+ rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
+ return
+ }
+ resolvedHome, err := filepath.EvalSymlinks(home)
+ if err != nil {
+ rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home)
+ return
+ }
+ runtimeDir = filepath.Join(resolvedHome, "rundir")
+ }
+ rootlessRuntimeDir = runtimeDir
+ })
+
+ if rootlessRuntimeDirError != nil {
+ return "", rootlessRuntimeDirError
+ }
+ return rootlessRuntimeDir, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/config/util_windows.go b/vendor/github.com/containers/common/pkg/config/util_windows.go
new file mode 100644
index 000000000..995301f5d
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/util_windows.go
@@ -0,0 +1,12 @@
+// +build windows
+
+package config
+
+import (
+ "github.com/pkg/errors"
+)
+
+// getRuntimeDir returns the runtime directory
+func getRuntimeDir() (string, error) {
+ return "", errors.New("this function is not implemented for windows")
+}
diff --git a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go b/vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go
new file mode 100644
index 000000000..4f441c32c
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go
@@ -0,0 +1,22 @@
+// +build linux,cgo
+
+package unshare
+
+import (
+ "unsafe"
+)
+
+/*
+#cgo remoteclient CFLAGS: -Wall -Werror
+#include <stdlib.h>
+*/
+import "C"
+
+func getenv(name string) string {
+ cName := C.CString(name)
+ defer C.free(unsafe.Pointer(cName))
+
+ value := C.GoString(C.getenv(cName))
+
+ return value
+}
diff --git a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go b/vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go
new file mode 100644
index 000000000..a5005403a
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go
@@ -0,0 +1,11 @@
+// +build linux,!cgo
+
+package unshare
+
+import (
+ "os"
+)
+
+func getenv(name string) string {
+ return os.Getenv(name)
+}
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go b/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go
index ed83908c2..ef33ab8eb 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go
+++ b/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go
@@ -50,6 +50,31 @@ func Command(args ...string) *Cmd {
}
}
+func getRootlessUID() int {
+ uidEnv := getenv("_CONTAINERS_ROOTLESS_UID")
+ if uidEnv != "" {
+ u, _ := strconv.Atoi(uidEnv)
+ return u
+ }
+ return os.Geteuid()
+}
+
+func getRootlessGID() int {
+ gidEnv := getenv("_CONTAINERS_ROOTLESS_GID")
+ if gidEnv != "" {
+ u, _ := strconv.Atoi(gidEnv)
+ return u
+ }
+
+ /* If the _CONTAINERS_ROOTLESS_UID is set, assume the gid==uid. */
+ uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
+ if uidEnv != "" {
+ u, _ := strconv.Atoi(uidEnv)
+ return u
+ }
+ return os.Getegid()
+}
+
func (c *Cmd) Start() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -61,10 +86,10 @@ func (c *Cmd) Start() error {
c.Env = append(c.Env, fmt.Sprintf("_Containers-unshare=%d", c.UnshareFlags))
// Please the libpod "rootless" package to find the expected env variables.
- if os.Geteuid() != 0 {
+ if IsRootless() {
c.Env = append(c.Env, "_CONTAINERS_USERNS_CONFIGURED=done")
- c.Env = append(c.Env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%d", os.Geteuid()))
- c.Env = append(c.Env, fmt.Sprintf("_CONTAINERS_ROOTLESS_GID=%d", os.Getegid()))
+ c.Env = append(c.Env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%d", getRootlessUID()))
+ c.Env = append(c.Env, fmt.Sprintf("_CONTAINERS_ROOTLESS_GID=%d", getRootlessGID()))
}
// Create the pipe for reading the child's PID.
@@ -318,14 +343,14 @@ const (
// IsRootless tells us if we are running in rootless mode
func IsRootless() bool {
isRootlessOnce.Do(func() {
- isRootless = os.Geteuid() != 0 || os.Getenv(UsernsEnvName) != ""
+ isRootless = getRootlessUID() != 0 || getenv(UsernsEnvName) != ""
})
return isRootless
}
// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
- uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
+ uidEnv := getenv("_CONTAINERS_ROOTLESS_UID")
if uidEnv != "" {
u, _ := strconv.Atoi(uidEnv)
return u
diff --git a/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md b/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md
new file mode 100644
index 000000000..be0791620
--- /dev/null
+++ b/vendor/github.com/containers/storage/CODE-OF-CONDUCT.md
@@ -0,0 +1,3 @@
+## The Containers Storage Project Community Code of Conduct
+
+The Containers Storage project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
diff --git a/vendor/github.com/containers/storage/Makefile b/vendor/github.com/containers/storage/Makefile
index 1b69d6060..09937303b 100644
--- a/vendor/github.com/containers/storage/Makefile
+++ b/vendor/github.com/containers/storage/Makefile
@@ -54,19 +54,19 @@ sources := $(wildcard *.go cmd/containers-storage/*.go drivers/*.go drivers/*/*.
containers-storage: $(sources) ## build using gc on the host
$(GO_BUILD) -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
-layers_ffjson.go: layers.go
+layers_ffjson.go: $(FFJSON) layers.go
$(RM) $@
$(FFJSON) layers.go
-images_ffjson.go: images.go
+images_ffjson.go: $(FFJSON) images.go
$(RM) $@
$(FFJSON) images.go
-containers_ffjson.go: containers.go
+containers_ffjson.go: $(FFJSON) containers.go
$(RM) $@
$(FFJSON) containers.go
-pkg/archive/archive_ffjson.go: pkg/archive/archive.go
+pkg/archive/archive_ffjson.go: $(FFJSON) pkg/archive/archive.go
$(RM) $@
$(FFJSON) pkg/archive/archive.go
@@ -118,6 +118,9 @@ validate: ## validate DCO, gofmt, ./pkg/ isolation, golint,\ngo vet and vendor u
install.tools:
make -C tests/tools
+$(FFJSON):
+ make -C tests/tools build/ffjson
+
install.docs: docs
make -C docs install
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 98e863cdf..15b989e39 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.15.8
+1.16.0
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index ba40f9c14..84dd86a20 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -7,10 +7,10 @@ require (
github.com/Microsoft/hcsshim v0.8.7
github.com/docker/docker v0.0.0-20171019062838-86f080cff091 // indirect
github.com/docker/go-units v0.4.0
- github.com/klauspost/compress v1.9.8
+ github.com/klauspost/compress v1.10.0
github.com/klauspost/cpuid v1.2.1 // indirect
github.com/klauspost/pgzip v1.2.1
- github.com/mattn/go-shellwords v1.0.9
+ github.com/mattn/go-shellwords v1.0.10
github.com/mistifyio/go-zfs v2.1.1+incompatible
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/runc v1.0.0-rc9
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index e2785594d..c2029949a 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -79,6 +79,8 @@ github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug2
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/compress v1.10.0 h1:92XGj1AcYzA6UrVdd4qIIBrT8OroryvRvdmg/IfmC7Y=
+github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
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=
@@ -93,6 +95,8 @@ github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWeP
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/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
+github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM=
diff --git a/vendor/github.com/containers/storage/images_ffjson.go b/vendor/github.com/containers/storage/images_ffjson.go
index 0dde97c18..e1954ad04 100644
--- a/vendor/github.com/containers/storage/images_ffjson.go
+++ b/vendor/github.com/containers/storage/images_ffjson.go
@@ -1,5 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: ./images.go
+// source: images.go
package storage
diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go
new file mode 100644
index 000000000..3a1095226
--- /dev/null
+++ b/vendor/github.com/containers/storage/layers_ffjson.go
@@ -0,0 +1,2156 @@
+// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
+// source: layers.go
+
+package storage
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "github.com/containers/storage/pkg/archive"
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/opencontainers/go-digest"
+ fflib "github.com/pquerna/ffjson/fflib/v1"
+)
+
+// MarshalJSON marshal bytes to json - template
+func (j *DiffOptions) MarshalJSON() ([]byte, error) {
+ var buf fflib.Buffer
+ if j == nil {
+ buf.WriteString("null")
+ return buf.Bytes(), nil
+ }
+ err := j.MarshalJSONBuf(&buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// MarshalJSONBuf marshal buff to json - template
+func (j *DiffOptions) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
+ if j == nil {
+ buf.WriteString("null")
+ return nil
+ }
+ var err error
+ var obj []byte
+ _ = obj
+ _ = err
+ if j.Compression != nil {
+ buf.WriteString(`{"Compression":`)
+ fflib.FormatBits2(buf, uint64(*j.Compression), 10, *j.Compression < 0)
+ } else {
+ buf.WriteString(`{"Compression":null`)
+ }
+ buf.WriteByte('}')
+ return nil
+}
+
+const (
+ ffjtDiffOptionsbase = iota
+ ffjtDiffOptionsnosuchkey
+
+ ffjtDiffOptionsCompression
+)
+
+var ffjKeyDiffOptionsCompression = []byte("Compression")
+
+// UnmarshalJSON umarshall json - template of ffjson
+func (j *DiffOptions) UnmarshalJSON(input []byte) error {
+ fs := fflib.NewFFLexer(input)
+ return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
+}
+
+// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
+func (j *DiffOptions) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
+ var err error
+ currentKey := ffjtDiffOptionsbase
+ _ = currentKey
+ tok := fflib.FFTok_init
+ wantedTok := fflib.FFTok_init
+
+mainparse:
+ for {
+ tok = fs.Scan()
+ // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+
+ switch state {
+
+ case fflib.FFParse_map_start:
+ if tok != fflib.FFTok_left_bracket {
+ wantedTok = fflib.FFTok_left_bracket
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_key
+ continue
+
+ case fflib.FFParse_after_value:
+ if tok == fflib.FFTok_comma {
+ state = fflib.FFParse_want_key
+ } else if tok == fflib.FFTok_right_bracket {
+ goto done
+ } else {
+ wantedTok = fflib.FFTok_comma
+ goto wrongtokenerror
+ }
+
+ case fflib.FFParse_want_key:
+ // json {} ended. goto exit. woo.
+ if tok == fflib.FFTok_right_bracket {
+ goto done
+ }
+ if tok != fflib.FFTok_string {
+ wantedTok = fflib.FFTok_string
+ goto wrongtokenerror
+ }
+
+ kn := fs.Output.Bytes()
+ if len(kn) <= 0 {
+ // "" case. hrm.
+ currentKey = ffjtDiffOptionsnosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ } else {
+ switch kn[0] {
+
+ case 'C':
+
+ if bytes.Equal(ffjKeyDiffOptionsCompression, kn) {
+ currentKey = ffjtDiffOptionsCompression
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ }
+
+ if fflib.EqualFoldRight(ffjKeyDiffOptionsCompression, kn) {
+ currentKey = ffjtDiffOptionsCompression
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ currentKey = ffjtDiffOptionsnosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case fflib.FFParse_want_colon:
+ if tok != fflib.FFTok_colon {
+ wantedTok = fflib.FFTok_colon
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_value
+ continue
+ case fflib.FFParse_want_value:
+
+ if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
+ switch currentKey {
+
+ case ffjtDiffOptionsCompression:
+ goto handle_Compression
+
+ case ffjtDiffOptionsnosuchkey:
+ err = fs.SkipField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ state = fflib.FFParse_after_value
+ goto mainparse
+ }
+ } else {
+ goto wantedvalue
+ }
+ }
+ }
+
+handle_Compression:
+
+ /* handler: j.Compression type=archive.Compression kind=int quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ j.Compression = nil
+
+ } else {
+
+ tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ ttypval := archive.Compression(tval)
+ j.Compression = &ttypval
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+wantedvalue:
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+wrongtokenerror:
+ return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
+tokerror:
+ if fs.BigError != nil {
+ return fs.WrapErr(fs.BigError)
+ }
+ err = fs.Error.ToError()
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ panic("ffjson-generated: unreachable, please report bug.")
+done:
+
+ return nil
+}
+
+// MarshalJSON marshal bytes to json - template
+func (j *Layer) MarshalJSON() ([]byte, error) {
+ var buf fflib.Buffer
+ if j == nil {
+ buf.WriteString("null")
+ return buf.Bytes(), nil
+ }
+ err := j.MarshalJSONBuf(&buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// MarshalJSONBuf marshal buff to json - template
+func (j *Layer) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
+ if j == nil {
+ buf.WriteString("null")
+ return nil
+ }
+ var err error
+ var obj []byte
+ _ = obj
+ _ = err
+ buf.WriteString(`{ "id":`)
+ fflib.WriteJsonString(buf, string(j.ID))
+ buf.WriteByte(',')
+ if len(j.Names) != 0 {
+ buf.WriteString(`"names":`)
+ if j.Names != nil {
+ buf.WriteString(`[`)
+ for i, v := range j.Names {
+ if i != 0 {
+ buf.WriteString(`,`)
+ }
+ fflib.WriteJsonString(buf, string(v))
+ }
+ buf.WriteString(`]`)
+ } else {
+ buf.WriteString(`null`)
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.Parent) != 0 {
+ buf.WriteString(`"parent":`)
+ fflib.WriteJsonString(buf, string(j.Parent))
+ buf.WriteByte(',')
+ }
+ if len(j.Metadata) != 0 {
+ buf.WriteString(`"metadata":`)
+ fflib.WriteJsonString(buf, string(j.Metadata))
+ buf.WriteByte(',')
+ }
+ if len(j.MountLabel) != 0 {
+ buf.WriteString(`"mountlabel":`)
+ fflib.WriteJsonString(buf, string(j.MountLabel))
+ buf.WriteByte(',')
+ }
+ if true {
+ buf.WriteString(`"created":`)
+
+ {
+
+ obj, err = j.Created.MarshalJSON()
+ if err != nil {
+ return err
+ }
+ buf.Write(obj)
+
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.CompressedDigest) != 0 {
+ buf.WriteString(`"compressed-diff-digest":`)
+ fflib.WriteJsonString(buf, string(j.CompressedDigest))
+ buf.WriteByte(',')
+ }
+ if j.CompressedSize != 0 {
+ buf.WriteString(`"compressed-size":`)
+ fflib.FormatBits2(buf, uint64(j.CompressedSize), 10, j.CompressedSize < 0)
+ buf.WriteByte(',')
+ }
+ if len(j.UncompressedDigest) != 0 {
+ buf.WriteString(`"diff-digest":`)
+ fflib.WriteJsonString(buf, string(j.UncompressedDigest))
+ buf.WriteByte(',')
+ }
+ if j.UncompressedSize != 0 {
+ buf.WriteString(`"diff-size":`)
+ fflib.FormatBits2(buf, uint64(j.UncompressedSize), 10, j.UncompressedSize < 0)
+ buf.WriteByte(',')
+ }
+ if j.CompressionType != 0 {
+ buf.WriteString(`"compression":`)
+ fflib.FormatBits2(buf, uint64(j.CompressionType), 10, j.CompressionType < 0)
+ buf.WriteByte(',')
+ }
+ if len(j.UIDs) != 0 {
+ buf.WriteString(`"uidset":`)
+ if j.UIDs != nil {
+ buf.WriteString(`[`)
+ for i, v := range j.UIDs {
+ if i != 0 {
+ buf.WriteString(`,`)
+ }
+ fflib.FormatBits2(buf, uint64(v), 10, false)
+ }
+ buf.WriteString(`]`)
+ } else {
+ buf.WriteString(`null`)
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.GIDs) != 0 {
+ buf.WriteString(`"gidset":`)
+ if j.GIDs != nil {
+ buf.WriteString(`[`)
+ for i, v := range j.GIDs {
+ if i != 0 {
+ buf.WriteString(`,`)
+ }
+ fflib.FormatBits2(buf, uint64(v), 10, false)
+ }
+ buf.WriteString(`]`)
+ } else {
+ buf.WriteString(`null`)
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.Flags) != 0 {
+ buf.WriteString(`"flags":`)
+ /* Falling back. type=map[string]interface {} kind=map */
+ err = buf.Encode(j.Flags)
+ if err != nil {
+ return err
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.UIDMap) != 0 {
+ buf.WriteString(`"uidmap":`)
+ if j.UIDMap != nil {
+ buf.WriteString(`[`)
+ for i, v := range j.UIDMap {
+ if i != 0 {
+ buf.WriteString(`,`)
+ }
+ /* Struct fall back. type=idtools.IDMap kind=struct */
+ err = buf.Encode(&v)
+ if err != nil {
+ return err
+ }
+ }
+ buf.WriteString(`]`)
+ } else {
+ buf.WriteString(`null`)
+ }
+ buf.WriteByte(',')
+ }
+ if len(j.GIDMap) != 0 {
+ buf.WriteString(`"gidmap":`)
+ if j.GIDMap != nil {
+ buf.WriteString(`[`)
+ for i, v := range j.GIDMap {
+ if i != 0 {
+ buf.WriteString(`,`)
+ }
+ /* Struct fall back. type=idtools.IDMap kind=struct */
+ err = buf.Encode(&v)
+ if err != nil {
+ return err
+ }
+ }
+ buf.WriteString(`]`)
+ } else {
+ buf.WriteString(`null`)
+ }
+ buf.WriteByte(',')
+ }
+ buf.Rewind(1)
+ buf.WriteByte('}')
+ return nil
+}
+
+const (
+ ffjtLayerbase = iota
+ ffjtLayernosuchkey
+
+ ffjtLayerID
+
+ ffjtLayerNames
+
+ ffjtLayerParent
+
+ ffjtLayerMetadata
+
+ ffjtLayerMountLabel
+
+ ffjtLayerCreated
+
+ ffjtLayerCompressedDigest
+
+ ffjtLayerCompressedSize
+
+ ffjtLayerUncompressedDigest
+
+ ffjtLayerUncompressedSize
+
+ ffjtLayerCompressionType
+
+ ffjtLayerUIDs
+
+ ffjtLayerGIDs
+
+ ffjtLayerFlags
+
+ ffjtLayerUIDMap
+
+ ffjtLayerGIDMap
+)
+
+var ffjKeyLayerID = []byte("id")
+
+var ffjKeyLayerNames = []byte("names")
+
+var ffjKeyLayerParent = []byte("parent")
+
+var ffjKeyLayerMetadata = []byte("metadata")
+
+var ffjKeyLayerMountLabel = []byte("mountlabel")
+
+var ffjKeyLayerCreated = []byte("created")
+
+var ffjKeyLayerCompressedDigest = []byte("compressed-diff-digest")
+
+var ffjKeyLayerCompressedSize = []byte("compressed-size")
+
+var ffjKeyLayerUncompressedDigest = []byte("diff-digest")
+
+var ffjKeyLayerUncompressedSize = []byte("diff-size")
+
+var ffjKeyLayerCompressionType = []byte("compression")
+
+var ffjKeyLayerUIDs = []byte("uidset")
+
+var ffjKeyLayerGIDs = []byte("gidset")
+
+var ffjKeyLayerFlags = []byte("flags")
+
+var ffjKeyLayerUIDMap = []byte("uidmap")
+
+var ffjKeyLayerGIDMap = []byte("gidmap")
+
+// UnmarshalJSON umarshall json - template of ffjson
+func (j *Layer) UnmarshalJSON(input []byte) error {
+ fs := fflib.NewFFLexer(input)
+ return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
+}
+
+// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
+func (j *Layer) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
+ var err error
+ currentKey := ffjtLayerbase
+ _ = currentKey
+ tok := fflib.FFTok_init
+ wantedTok := fflib.FFTok_init
+
+mainparse:
+ for {
+ tok = fs.Scan()
+ // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+
+ switch state {
+
+ case fflib.FFParse_map_start:
+ if tok != fflib.FFTok_left_bracket {
+ wantedTok = fflib.FFTok_left_bracket
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_key
+ continue
+
+ case fflib.FFParse_after_value:
+ if tok == fflib.FFTok_comma {
+ state = fflib.FFParse_want_key
+ } else if tok == fflib.FFTok_right_bracket {
+ goto done
+ } else {
+ wantedTok = fflib.FFTok_comma
+ goto wrongtokenerror
+ }
+
+ case fflib.FFParse_want_key:
+ // json {} ended. goto exit. woo.
+ if tok == fflib.FFTok_right_bracket {
+ goto done
+ }
+ if tok != fflib.FFTok_string {
+ wantedTok = fflib.FFTok_string
+ goto wrongtokenerror
+ }
+
+ kn := fs.Output.Bytes()
+ if len(kn) <= 0 {
+ // "" case. hrm.
+ currentKey = ffjtLayernosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ } else {
+ switch kn[0] {
+
+ case 'c':
+
+ if bytes.Equal(ffjKeyLayerCreated, kn) {
+ currentKey = ffjtLayerCreated
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerCompressedDigest, kn) {
+ currentKey = ffjtLayerCompressedDigest
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerCompressedSize, kn) {
+ currentKey = ffjtLayerCompressedSize
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerCompressionType, kn) {
+ currentKey = ffjtLayerCompressionType
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'd':
+
+ if bytes.Equal(ffjKeyLayerUncompressedDigest, kn) {
+ currentKey = ffjtLayerUncompressedDigest
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerUncompressedSize, kn) {
+ currentKey = ffjtLayerUncompressedSize
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'f':
+
+ if bytes.Equal(ffjKeyLayerFlags, kn) {
+ currentKey = ffjtLayerFlags
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'g':
+
+ if bytes.Equal(ffjKeyLayerGIDs, kn) {
+ currentKey = ffjtLayerGIDs
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerGIDMap, kn) {
+ currentKey = ffjtLayerGIDMap
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'i':
+
+ if bytes.Equal(ffjKeyLayerID, kn) {
+ currentKey = ffjtLayerID
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'm':
+
+ if bytes.Equal(ffjKeyLayerMetadata, kn) {
+ currentKey = ffjtLayerMetadata
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerMountLabel, kn) {
+ currentKey = ffjtLayerMountLabel
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'n':
+
+ if bytes.Equal(ffjKeyLayerNames, kn) {
+ currentKey = ffjtLayerNames
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'p':
+
+ if bytes.Equal(ffjKeyLayerParent, kn) {
+ currentKey = ffjtLayerParent
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'u':
+
+ if bytes.Equal(ffjKeyLayerUIDs, kn) {
+ currentKey = ffjtLayerUIDs
+ state = fflib.FFParse_want_colon
+ goto mainparse
+
+ } else if bytes.Equal(ffjKeyLayerUIDMap, kn) {
+ currentKey = ffjtLayerUIDMap
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerGIDMap, kn) {
+ currentKey = ffjtLayerGIDMap
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerUIDMap, kn) {
+ currentKey = ffjtLayerUIDMap
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerFlags, kn) {
+ currentKey = ffjtLayerFlags
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerGIDs, kn) {
+ currentKey = ffjtLayerGIDs
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerUIDs, kn) {
+ currentKey = ffjtLayerUIDs
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerCompressionType, kn) {
+ currentKey = ffjtLayerCompressionType
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerUncompressedSize, kn) {
+ currentKey = ffjtLayerUncompressedSize
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerUncompressedDigest, kn) {
+ currentKey = ffjtLayerUncompressedDigest
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerCompressedSize, kn) {
+ currentKey = ffjtLayerCompressedSize
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerCompressedDigest, kn) {
+ currentKey = ffjtLayerCompressedDigest
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerCreated, kn) {
+ currentKey = ffjtLayerCreated
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerMountLabel, kn) {
+ currentKey = ffjtLayerMountLabel
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerMetadata, kn) {
+ currentKey = ffjtLayerMetadata
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerParent, kn) {
+ currentKey = ffjtLayerParent
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.EqualFoldRight(ffjKeyLayerNames, kn) {
+ currentKey = ffjtLayerNames
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeyLayerID, kn) {
+ currentKey = ffjtLayerID
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ currentKey = ffjtLayernosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case fflib.FFParse_want_colon:
+ if tok != fflib.FFTok_colon {
+ wantedTok = fflib.FFTok_colon
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_value
+ continue
+ case fflib.FFParse_want_value:
+
+ if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
+ switch currentKey {
+
+ case ffjtLayerID:
+ goto handle_ID
+
+ case ffjtLayerNames:
+ goto handle_Names
+
+ case ffjtLayerParent:
+ goto handle_Parent
+
+ case ffjtLayerMetadata:
+ goto handle_Metadata
+
+ case ffjtLayerMountLabel:
+ goto handle_MountLabel
+
+ case ffjtLayerCreated:
+ goto handle_Created
+
+ case ffjtLayerCompressedDigest:
+ goto handle_CompressedDigest
+
+ case ffjtLayerCompressedSize:
+ goto handle_CompressedSize
+
+ case ffjtLayerUncompressedDigest:
+ goto handle_UncompressedDigest
+
+ case ffjtLayerUncompressedSize:
+ goto handle_UncompressedSize
+
+ case ffjtLayerCompressionType:
+ goto handle_CompressionType
+
+ case ffjtLayerUIDs:
+ goto handle_UIDs
+
+ case ffjtLayerGIDs:
+ goto handle_GIDs
+
+ case ffjtLayerFlags:
+ goto handle_Flags
+
+ case ffjtLayerUIDMap:
+ goto handle_UIDMap
+
+ case ffjtLayerGIDMap:
+ goto handle_GIDMap
+
+ case ffjtLayernosuchkey:
+ err = fs.SkipField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ state = fflib.FFParse_after_value
+ goto mainparse
+ }
+ } else {
+ goto wantedvalue
+ }
+ }
+ }
+
+handle_ID:
+
+ /* handler: j.ID type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.ID = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_Names:
+
+ /* handler: j.Names type=[]string kind=slice quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.Names = nil
+ } else {
+
+ j.Names = []string{}
+
+ wantVal := true
+
+ for {
+
+ var tmpJNames string
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_brace {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: tmpJNames type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ tmpJNames = string(string(outBuf))
+
+ }
+ }
+
+ j.Names = append(j.Names, tmpJNames)
+
+ wantVal = false
+ }
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_Parent:
+
+ /* handler: j.Parent type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.Parent = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_Metadata:
+
+ /* handler: j.Metadata type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.Metadata = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_MountLabel:
+
+ /* handler: j.MountLabel type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.MountLabel = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_Created:
+
+ /* handler: j.Created type=time.Time kind=struct quoted=false*/
+
+ {
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tbuf, err := fs.CaptureField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ err = j.Created.UnmarshalJSON(tbuf)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ }
+ state = fflib.FFParse_after_value
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_CompressedDigest:
+
+ /* handler: j.CompressedDigest type=digest.Digest kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.CompressedDigest = digest.Digest(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_CompressedSize:
+
+ /* handler: j.CompressedSize type=int64 kind=int64 quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ j.CompressedSize = int64(tval)
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_UncompressedDigest:
+
+ /* handler: j.UncompressedDigest type=digest.Digest kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.UncompressedDigest = digest.Digest(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_UncompressedSize:
+
+ /* handler: j.UncompressedSize type=int64 kind=int64 quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ j.UncompressedSize = int64(tval)
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_CompressionType:
+
+ /* handler: j.CompressionType type=archive.Compression kind=int quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ j.CompressionType = archive.Compression(tval)
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_UIDs:
+
+ /* handler: j.UIDs type=[]uint32 kind=slice quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.UIDs = nil
+ } else {
+
+ j.UIDs = []uint32{}
+
+ wantVal := true
+
+ for {
+
+ var tmpJUIDs uint32
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_brace {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: tmpJUIDs type=uint32 kind=uint32 quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ tmpJUIDs = uint32(tval)
+
+ }
+ }
+
+ j.UIDs = append(j.UIDs, tmpJUIDs)
+
+ wantVal = false
+ }
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_GIDs:
+
+ /* handler: j.GIDs type=[]uint32 kind=slice quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.GIDs = nil
+ } else {
+
+ j.GIDs = []uint32{}
+
+ wantVal := true
+
+ for {
+
+ var tmpJGIDs uint32
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_brace {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: tmpJGIDs type=uint32 kind=uint32 quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ tmpJGIDs = uint32(tval)
+
+ }
+ }
+
+ j.GIDs = append(j.GIDs, tmpJGIDs)
+
+ wantVal = false
+ }
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_Flags:
+
+ /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.Flags = nil
+ } else {
+
+ j.Flags = make(map[string]interface{}, 0)
+
+ wantVal := true
+
+ for {
+
+ var k string
+
+ var tmpJFlags interface{}
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_bracket {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: k type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ k = string(string(outBuf))
+
+ }
+ }
+
+ // Expect ':' after key
+ tok = fs.Scan()
+ if tok != fflib.FFTok_colon {
+ return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok))
+ }
+
+ tok = fs.Scan()
+ /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/
+
+ {
+ /* Falling back. type=interface {} kind=interface */
+ tbuf, err := fs.CaptureField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ err = json.Unmarshal(tbuf, &tmpJFlags)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ }
+
+ j.Flags[k] = tmpJFlags
+
+ wantVal = false
+ }
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_UIDMap:
+
+ /* handler: j.UIDMap type=[]idtools.IDMap kind=slice quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.UIDMap = nil
+ } else {
+
+ j.UIDMap = []idtools.IDMap{}
+
+ wantVal := true
+
+ for {
+
+ var tmpJUIDMap idtools.IDMap
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_brace {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: tmpJUIDMap type=idtools.IDMap kind=struct quoted=false*/
+
+ {
+ /* Falling back. type=idtools.IDMap kind=struct */
+ tbuf, err := fs.CaptureField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ err = json.Unmarshal(tbuf, &tmpJUIDMap)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ }
+
+ j.UIDMap = append(j.UIDMap, tmpJUIDMap)
+
+ wantVal = false
+ }
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_GIDMap:
+
+ /* handler: j.GIDMap type=[]idtools.IDMap kind=slice quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+ j.GIDMap = nil
+ } else {
+
+ j.GIDMap = []idtools.IDMap{}
+
+ wantVal := true
+
+ for {
+
+ var tmpJGIDMap idtools.IDMap
+
+ tok = fs.Scan()
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+ if tok == fflib.FFTok_right_brace {
+ break
+ }
+
+ if tok == fflib.FFTok_comma {
+ if wantVal == true {
+ // TODO(pquerna): this isn't an ideal error message, this handles
+ // things like [,,,] as an array value.
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+ }
+ continue
+ } else {
+ wantVal = true
+ }
+
+ /* handler: tmpJGIDMap type=idtools.IDMap kind=struct quoted=false*/
+
+ {
+ /* Falling back. type=idtools.IDMap kind=struct */
+ tbuf, err := fs.CaptureField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ err = json.Unmarshal(tbuf, &tmpJGIDMap)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ }
+
+ j.GIDMap = append(j.GIDMap, tmpJGIDMap)
+
+ wantVal = false
+ }
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+wantedvalue:
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+wrongtokenerror:
+ return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
+tokerror:
+ if fs.BigError != nil {
+ return fs.WrapErr(fs.BigError)
+ }
+ err = fs.Error.ToError()
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ panic("ffjson-generated: unreachable, please report bug.")
+done:
+
+ return nil
+}
+
+// MarshalJSON marshal bytes to json - template
+func (j *layerMountPoint) MarshalJSON() ([]byte, error) {
+ var buf fflib.Buffer
+ if j == nil {
+ buf.WriteString("null")
+ return buf.Bytes(), nil
+ }
+ err := j.MarshalJSONBuf(&buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// MarshalJSONBuf marshal buff to json - template
+func (j *layerMountPoint) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
+ if j == nil {
+ buf.WriteString("null")
+ return nil
+ }
+ var err error
+ var obj []byte
+ _ = obj
+ _ = err
+ buf.WriteString(`{"id":`)
+ fflib.WriteJsonString(buf, string(j.ID))
+ buf.WriteString(`,"path":`)
+ fflib.WriteJsonString(buf, string(j.MountPoint))
+ buf.WriteString(`,"count":`)
+ fflib.FormatBits2(buf, uint64(j.MountCount), 10, j.MountCount < 0)
+ buf.WriteByte('}')
+ return nil
+}
+
+const (
+ ffjtlayerMountPointbase = iota
+ ffjtlayerMountPointnosuchkey
+
+ ffjtlayerMountPointID
+
+ ffjtlayerMountPointMountPoint
+
+ ffjtlayerMountPointMountCount
+)
+
+var ffjKeylayerMountPointID = []byte("id")
+
+var ffjKeylayerMountPointMountPoint = []byte("path")
+
+var ffjKeylayerMountPointMountCount = []byte("count")
+
+// UnmarshalJSON umarshall json - template of ffjson
+func (j *layerMountPoint) UnmarshalJSON(input []byte) error {
+ fs := fflib.NewFFLexer(input)
+ return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
+}
+
+// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
+func (j *layerMountPoint) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
+ var err error
+ currentKey := ffjtlayerMountPointbase
+ _ = currentKey
+ tok := fflib.FFTok_init
+ wantedTok := fflib.FFTok_init
+
+mainparse:
+ for {
+ tok = fs.Scan()
+ // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+
+ switch state {
+
+ case fflib.FFParse_map_start:
+ if tok != fflib.FFTok_left_bracket {
+ wantedTok = fflib.FFTok_left_bracket
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_key
+ continue
+
+ case fflib.FFParse_after_value:
+ if tok == fflib.FFTok_comma {
+ state = fflib.FFParse_want_key
+ } else if tok == fflib.FFTok_right_bracket {
+ goto done
+ } else {
+ wantedTok = fflib.FFTok_comma
+ goto wrongtokenerror
+ }
+
+ case fflib.FFParse_want_key:
+ // json {} ended. goto exit. woo.
+ if tok == fflib.FFTok_right_bracket {
+ goto done
+ }
+ if tok != fflib.FFTok_string {
+ wantedTok = fflib.FFTok_string
+ goto wrongtokenerror
+ }
+
+ kn := fs.Output.Bytes()
+ if len(kn) <= 0 {
+ // "" case. hrm.
+ currentKey = ffjtlayerMountPointnosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ } else {
+ switch kn[0] {
+
+ case 'c':
+
+ if bytes.Equal(ffjKeylayerMountPointMountCount, kn) {
+ currentKey = ffjtlayerMountPointMountCount
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'i':
+
+ if bytes.Equal(ffjKeylayerMountPointID, kn) {
+ currentKey = ffjtlayerMountPointID
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case 'p':
+
+ if bytes.Equal(ffjKeylayerMountPointMountPoint, kn) {
+ currentKey = ffjtlayerMountPointMountPoint
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountCount, kn) {
+ currentKey = ffjtlayerMountPointMountCount
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountPoint, kn) {
+ currentKey = ffjtlayerMountPointMountPoint
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointID, kn) {
+ currentKey = ffjtlayerMountPointID
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ currentKey = ffjtlayerMountPointnosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case fflib.FFParse_want_colon:
+ if tok != fflib.FFTok_colon {
+ wantedTok = fflib.FFTok_colon
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_value
+ continue
+ case fflib.FFParse_want_value:
+
+ if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
+ switch currentKey {
+
+ case ffjtlayerMountPointID:
+ goto handle_ID
+
+ case ffjtlayerMountPointMountPoint:
+ goto handle_MountPoint
+
+ case ffjtlayerMountPointMountCount:
+ goto handle_MountCount
+
+ case ffjtlayerMountPointnosuchkey:
+ err = fs.SkipField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ state = fflib.FFParse_after_value
+ goto mainparse
+ }
+ } else {
+ goto wantedvalue
+ }
+ }
+ }
+
+handle_ID:
+
+ /* handler: j.ID type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.ID = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_MountPoint:
+
+ /* handler: j.MountPoint type=string kind=string quoted=false*/
+
+ {
+
+ {
+ if tok != fflib.FFTok_string && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok))
+ }
+ }
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ outBuf := fs.Output.Bytes()
+
+ j.MountPoint = string(string(outBuf))
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+handle_MountCount:
+
+ /* handler: j.MountCount type=int kind=int quoted=false*/
+
+ {
+ if tok != fflib.FFTok_integer && tok != fflib.FFTok_null {
+ return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok))
+ }
+ }
+
+ {
+
+ if tok == fflib.FFTok_null {
+
+ } else {
+
+ tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64)
+
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+
+ j.MountCount = int(tval)
+
+ }
+ }
+
+ state = fflib.FFParse_after_value
+ goto mainparse
+
+wantedvalue:
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+wrongtokenerror:
+ return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
+tokerror:
+ if fs.BigError != nil {
+ return fs.WrapErr(fs.BigError)
+ }
+ err = fs.Error.ToError()
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ panic("ffjson-generated: unreachable, please report bug.")
+done:
+
+ return nil
+}
+
+// MarshalJSON marshal bytes to json - template
+func (j *layerStore) MarshalJSON() ([]byte, error) {
+ var buf fflib.Buffer
+ if j == nil {
+ buf.WriteString("null")
+ return buf.Bytes(), nil
+ }
+ err := j.MarshalJSONBuf(&buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// MarshalJSONBuf marshal buff to json - template
+func (j *layerStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
+ if j == nil {
+ buf.WriteString("null")
+ return nil
+ }
+ var err error
+ var obj []byte
+ _ = obj
+ _ = err
+ buf.WriteString(`{}`)
+ return nil
+}
+
+const (
+ ffjtlayerStorebase = iota
+ ffjtlayerStorenosuchkey
+)
+
+// UnmarshalJSON umarshall json - template of ffjson
+func (j *layerStore) UnmarshalJSON(input []byte) error {
+ fs := fflib.NewFFLexer(input)
+ return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
+}
+
+// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
+func (j *layerStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
+ var err error
+ currentKey := ffjtlayerStorebase
+ _ = currentKey
+ tok := fflib.FFTok_init
+ wantedTok := fflib.FFTok_init
+
+mainparse:
+ for {
+ tok = fs.Scan()
+ // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+
+ switch state {
+
+ case fflib.FFParse_map_start:
+ if tok != fflib.FFTok_left_bracket {
+ wantedTok = fflib.FFTok_left_bracket
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_key
+ continue
+
+ case fflib.FFParse_after_value:
+ if tok == fflib.FFTok_comma {
+ state = fflib.FFParse_want_key
+ } else if tok == fflib.FFTok_right_bracket {
+ goto done
+ } else {
+ wantedTok = fflib.FFTok_comma
+ goto wrongtokenerror
+ }
+
+ case fflib.FFParse_want_key:
+ // json {} ended. goto exit. woo.
+ if tok == fflib.FFTok_right_bracket {
+ goto done
+ }
+ if tok != fflib.FFTok_string {
+ wantedTok = fflib.FFTok_string
+ goto wrongtokenerror
+ }
+
+ kn := fs.Output.Bytes()
+ if len(kn) <= 0 {
+ // "" case. hrm.
+ currentKey = ffjtlayerStorenosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ } else {
+ switch kn[0] {
+
+ }
+
+ currentKey = ffjtlayerStorenosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case fflib.FFParse_want_colon:
+ if tok != fflib.FFTok_colon {
+ wantedTok = fflib.FFTok_colon
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_value
+ continue
+ case fflib.FFParse_want_value:
+
+ if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
+ switch currentKey {
+
+ case ffjtlayerStorenosuchkey:
+ err = fs.SkipField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ state = fflib.FFParse_after_value
+ goto mainparse
+ }
+ } else {
+ goto wantedvalue
+ }
+ }
+ }
+
+wantedvalue:
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+wrongtokenerror:
+ return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
+tokerror:
+ if fs.BigError != nil {
+ return fs.WrapErr(fs.BigError)
+ }
+ err = fs.Error.ToError()
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ panic("ffjson-generated: unreachable, please report bug.")
+done:
+
+ return nil
+}
+
+// MarshalJSON marshal bytes to json - template
+func (j *simpleGetCloser) MarshalJSON() ([]byte, error) {
+ var buf fflib.Buffer
+ if j == nil {
+ buf.WriteString("null")
+ return buf.Bytes(), nil
+ }
+ err := j.MarshalJSONBuf(&buf)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// MarshalJSONBuf marshal buff to json - template
+func (j *simpleGetCloser) MarshalJSONBuf(buf fflib.EncodingBuffer) error {
+ if j == nil {
+ buf.WriteString("null")
+ return nil
+ }
+ var err error
+ var obj []byte
+ _ = obj
+ _ = err
+ buf.WriteString(`{}`)
+ return nil
+}
+
+const (
+ ffjtsimpleGetCloserbase = iota
+ ffjtsimpleGetClosernosuchkey
+)
+
+// UnmarshalJSON umarshall json - template of ffjson
+func (j *simpleGetCloser) UnmarshalJSON(input []byte) error {
+ fs := fflib.NewFFLexer(input)
+ return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start)
+}
+
+// UnmarshalJSONFFLexer fast json unmarshall - template ffjson
+func (j *simpleGetCloser) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error {
+ var err error
+ currentKey := ffjtsimpleGetCloserbase
+ _ = currentKey
+ tok := fflib.FFTok_init
+ wantedTok := fflib.FFTok_init
+
+mainparse:
+ for {
+ tok = fs.Scan()
+ // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state))
+ if tok == fflib.FFTok_error {
+ goto tokerror
+ }
+
+ switch state {
+
+ case fflib.FFParse_map_start:
+ if tok != fflib.FFTok_left_bracket {
+ wantedTok = fflib.FFTok_left_bracket
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_key
+ continue
+
+ case fflib.FFParse_after_value:
+ if tok == fflib.FFTok_comma {
+ state = fflib.FFParse_want_key
+ } else if tok == fflib.FFTok_right_bracket {
+ goto done
+ } else {
+ wantedTok = fflib.FFTok_comma
+ goto wrongtokenerror
+ }
+
+ case fflib.FFParse_want_key:
+ // json {} ended. goto exit. woo.
+ if tok == fflib.FFTok_right_bracket {
+ goto done
+ }
+ if tok != fflib.FFTok_string {
+ wantedTok = fflib.FFTok_string
+ goto wrongtokenerror
+ }
+
+ kn := fs.Output.Bytes()
+ if len(kn) <= 0 {
+ // "" case. hrm.
+ currentKey = ffjtsimpleGetClosernosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ } else {
+ switch kn[0] {
+
+ }
+
+ currentKey = ffjtsimpleGetClosernosuchkey
+ state = fflib.FFParse_want_colon
+ goto mainparse
+ }
+
+ case fflib.FFParse_want_colon:
+ if tok != fflib.FFTok_colon {
+ wantedTok = fflib.FFTok_colon
+ goto wrongtokenerror
+ }
+ state = fflib.FFParse_want_value
+ continue
+ case fflib.FFParse_want_value:
+
+ if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null {
+ switch currentKey {
+
+ case ffjtsimpleGetClosernosuchkey:
+ err = fs.SkipField(tok)
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ state = fflib.FFParse_after_value
+ goto mainparse
+ }
+ } else {
+ goto wantedvalue
+ }
+ }
+ }
+
+wantedvalue:
+ return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok))
+wrongtokenerror:
+ return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String()))
+tokerror:
+ if fs.BigError != nil {
+ return fs.WrapErr(fs.BigError)
+ }
+ err = fs.Error.ToError()
+ if err != nil {
+ return fs.WrapErr(err)
+ }
+ panic("ffjson-generated: unreachable, please report bug.")
+done:
+
+ return nil
+}
diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go
index c001fbecb..d28ba9d69 100644
--- a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go
+++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go
@@ -1,23 +1,96 @@
-// +build linux
-
package homedir
+// Copyright 2013-2018 Docker, Inc.
+// NOTE: this package has originally been copied from github.com/docker/docker.
+
import (
+ "errors"
"os"
-
- "github.com/containers/storage/pkg/idtools"
+ "path/filepath"
+ "strings"
)
-// GetStatic returns the home directory for the current user without calling
-// os/user.Current(). This is useful for static-linked binary on glibc-based
-// system, because a call to os/user.Current() in a static binary leads to
-// segfault due to a glibc issue that won't be fixed in a short term.
-// (#29344, golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341)
-func GetStatic() (string, error) {
- uid := os.Getuid()
- usr, err := idtools.LookupUID(uid)
+// GetRuntimeDir returns XDG_RUNTIME_DIR.
+// XDG_RUNTIME_DIR is typically configured via pam_systemd.
+// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set.
+//
+// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
+func GetRuntimeDir() (string, error) {
+ if xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR"); xdgRuntimeDir != "" {
+ return xdgRuntimeDir, nil
+ }
+ return "", errors.New("could not get XDG_RUNTIME_DIR")
+}
+
+// StickRuntimeDirContents sets the sticky bit on files that are under
+// XDG_RUNTIME_DIR, so that the files won't be periodically removed by the system.
+//
+// StickyRuntimeDir returns slice of sticked files.
+// StickyRuntimeDir returns nil error if XDG_RUNTIME_DIR is not set.
+//
+// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
+func StickRuntimeDirContents(files []string) ([]string, error) {
+ runtimeDir, err := GetRuntimeDir()
if err != nil {
- return "", err
+ // ignore error if runtimeDir is empty
+ return nil, nil
+ }
+ runtimeDir, err = filepath.Abs(runtimeDir)
+ if err != nil {
+ return nil, err
+ }
+ var sticked []string
+ for _, f := range files {
+ f, err = filepath.Abs(f)
+ if err != nil {
+ return sticked, err
+ }
+ if strings.HasPrefix(f, runtimeDir+"/") {
+ if err = stick(f); err != nil {
+ return sticked, err
+ }
+ sticked = append(sticked, f)
+ }
+ }
+ return sticked, nil
+}
+
+func stick(f string) error {
+ st, err := os.Stat(f)
+ if err != nil {
+ return err
+ }
+ m := st.Mode()
+ m |= os.ModeSticky
+ return os.Chmod(f, m)
+}
+
+// GetDataHome returns XDG_DATA_HOME.
+// GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set.
+//
+// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
+func GetDataHome() (string, error) {
+ if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" {
+ return xdgDataHome, nil
+ }
+ home := os.Getenv("HOME")
+ if home == "" {
+ return "", errors.New("could not get either XDG_DATA_HOME or HOME")
+ }
+ return filepath.Join(home, ".local", "share"), nil
+}
+
+// GetConfigHome returns XDG_CONFIG_HOME.
+// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set.
+//
+// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
+func GetConfigHome() (string, error) {
+ if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
+ return xdgConfigHome, nil
+ }
+ home := os.Getenv("HOME")
+ if home == "" {
+ return "", errors.New("could not get either XDG_CONFIG_HOME or HOME")
}
- return usr.Home, nil
+ return filepath.Join(home, ".config"), nil
}
diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go
index 6b96b856f..f7bcfb878 100644
--- a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go
+++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go
@@ -2,12 +2,29 @@
package homedir
+// Copyright 2013-2018 Docker, Inc.
+// NOTE: this package has originally been copied from github.com/docker/docker.
+
import (
"errors"
)
-// GetStatic is not needed for non-linux systems.
-// (Precisely, it is needed only for glibc-based linux systems.)
-func GetStatic() (string, error) {
- return "", errors.New("homedir.GetStatic() is not supported on this system")
+// GetRuntimeDir is unsupported on non-linux system.
+func GetRuntimeDir() (string, error) {
+ return "", errors.New("homedir.GetRuntimeDir() is not supported on this system")
+}
+
+// StickRuntimeDirContents is unsupported on non-linux system.
+func StickRuntimeDirContents(files []string) ([]string, error) {
+ return nil, errors.New("homedir.StickRuntimeDirContents() is not supported on this system")
+}
+
+// GetDataHome is unsupported on non-linux system.
+func GetDataHome() (string, error) {
+ return "", errors.New("homedir.GetDataHome() is not supported on this system")
+}
+
+// GetConfigHome is unsupported on non-linux system.
+func GetConfigHome() (string, error) {
+ return "", errors.New("homedir.GetConfigHome() is not supported on this system")
}
diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go
index f2a20ea8f..dcadb7e8d 100644
--- a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go
+++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go
@@ -2,10 +2,12 @@
package homedir
+// Copyright 2013-2018 Docker, Inc.
+// NOTE: this package has originally been copied from github.com/docker/docker.
+
import (
"os"
-
- "github.com/opencontainers/runc/libcontainer/user"
+ "os/user"
)
// Key returns the env var name for the user's home dir based on
@@ -17,11 +19,16 @@ func Key() string {
// Get returns the home directory of the current user with the help of
// environment variables depending on the target operating system.
// Returned path should be used with "path/filepath" to form new paths.
+//
+// If linking statically with cgo enabled against glibc, ensure the
+// osusergo build tag is used.
+//
+// If needing to do nss lookups, do not disable cgo or set osusergo.
func Get() string {
home := os.Getenv(Key())
if home == "" {
- if u, err := user.CurrentUser(); err == nil {
- return u.Home
+ if u, err := user.Current(); err == nil {
+ return u.HomeDir
}
}
return home
diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go
index fafdb2bbf..4f2615ed3 100644
--- a/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go
+++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_windows.go
@@ -1,5 +1,8 @@
package homedir
+// Copyright 2013-2018 Docker, Inc.
+// NOTE: this package has originally been copied from github.com/docker/docker.
+
import (
"os"
)
diff --git a/vendor/github.com/containers/storage/pkg/reexec/command_linux.go b/vendor/github.com/containers/storage/pkg/reexec/command_linux.go
index 1ae728a61..372bee732 100644
--- a/vendor/github.com/containers/storage/pkg/reexec/command_linux.go
+++ b/vendor/github.com/containers/storage/pkg/reexec/command_linux.go
@@ -5,9 +5,6 @@ package reexec
import (
"context"
"os/exec"
- "syscall"
-
- "golang.org/x/sys/unix"
)
// Self returns the path to the current process's binary.
@@ -16,28 +13,20 @@ func Self() string {
return "/proc/self/exe"
}
-// Command returns *exec.Cmd which has Path as current binary. Also it setting
-// SysProcAttr.Pdeathsig to SIGTERM.
+// Command returns *exec.Cmd which has Path as current binary.
// This will use the in-memory version (/proc/self/exe) of the current binary,
// it is thus safe to delete or replace the on-disk binary (os.Args[0]).
func Command(args ...string) *exec.Cmd {
cmd := exec.Command(Self())
cmd.Args = args
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: unix.SIGTERM,
- }
return cmd
}
-// CommandContext returns *exec.Cmd which has Path as current binary, and also
-// sets SysProcAttr.Pdeathsig to SIGTERM.
+// CommandContext returns *exec.Cmd which has Path as current binary.
// This will use the in-memory version (/proc/self/exe) of the current binary,
// it is thus safe to delete or replace the on-disk binary (os.Args[0]).
func CommandContext(ctx context.Context, args ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, Self())
cmd.Args = args
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: unix.SIGTERM,
- }
return cmd
}
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index b84be4424..d978c476d 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -20,6 +20,7 @@ import (
"github.com/containers/storage/pkg/archive"
cfg "github.com/containers/storage/pkg/config"
"github.com/containers/storage/pkg/directory"
+ "github.com/containers/storage/pkg/homedir"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/parsers"
@@ -3275,9 +3276,9 @@ const defaultConfigFile = "/etc/containers/storage.conf"
// DefaultConfigFile returns the path to the storage config file used
func DefaultConfigFile(rootless bool) (string, error) {
if rootless {
- home, err := homeDir()
- if err != nil {
- return "", errors.Wrapf(err, "cannot determine users homedir")
+ home := homedir.Get()
+ if home == "" {
+ return "", errors.New("cannot determine user's homedir")
}
return filepath.Join(home, ".config/containers/storage.conf"), nil
}
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index 28e0a8d6d..7e4b27d0f 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -4,12 +4,12 @@ import (
"fmt"
"os"
"os/exec"
- "os/user"
"path/filepath"
"strconv"
"strings"
"github.com/BurntSushi/toml"
+ "github.com/containers/storage/pkg/homedir"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/system"
"github.com/pkg/errors"
@@ -82,9 +82,8 @@ func GetRootlessRuntimeDir(rootlessUID int) (string, error) {
}
func getRootlessRuntimeDir(rootlessUID int) (string, error) {
- runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
-
- if runtimeDir != "" {
+ runtimeDir, err := homedir.GetRuntimeDir()
+ if err == nil {
return runtimeDir, nil
}
tmpDir := fmt.Sprintf("/run/user/%d", rootlessUID)
@@ -98,8 +97,8 @@ func getRootlessRuntimeDir(rootlessUID int) (string, error) {
} else {
return tmpDir, nil
}
- home, err := homeDir()
- if err != nil {
+ home := homedir.Get()
+ if home == "" {
return "", errors.Wrapf(err, "neither XDG_RUNTIME_DIR nor HOME was set non-empty")
}
resolvedHome, err := filepath.EvalSymlinks(home)
@@ -117,20 +116,23 @@ func getRootlessDirInfo(rootlessUID int) (string, string, error) {
return "", "", err
}
- dataDir := os.Getenv("XDG_DATA_HOME")
- if dataDir == "" {
- home, err := homeDir()
- if err != nil {
- return "", "", errors.Wrapf(err, "neither XDG_DATA_HOME nor HOME was set non-empty")
- }
- // runc doesn't like symlinks in the rootfs path, and at least
- // on CoreOS /home is a symlink to /var/home, so resolve any symlink.
- resolvedHome, err := filepath.EvalSymlinks(home)
- if err != nil {
- return "", "", errors.Wrapf(err, "cannot resolve %s", home)
- }
- dataDir = filepath.Join(resolvedHome, ".local", "share")
+ dataDir, err := homedir.GetDataHome()
+ if err == nil {
+ return dataDir, rootlessRuntime, nil
+ }
+
+ home := homedir.Get()
+ if home == "" {
+ return "", "", errors.Wrapf(err, "neither XDG_DATA_HOME nor HOME was set non-empty")
+ }
+ // runc doesn't like symlinks in the rootfs path, and at least
+ // on CoreOS /home is a symlink to /var/home, so resolve any symlink.
+ resolvedHome, err := filepath.EvalSymlinks(home)
+ if err != nil {
+ return "", "", errors.Wrapf(err, "cannot resolve %s", home)
}
+ dataDir = filepath.Join(resolvedHome, ".local", "share")
+
return dataDir, rootlessRuntime, nil
}
@@ -246,15 +248,3 @@ func DefaultStoreOptions(rootless bool, rootlessUID int) (StoreOptions, error) {
}
return storageOpts, nil
}
-
-func homeDir() (string, error) {
- home := os.Getenv("HOME")
- if home == "" {
- usr, err := user.Current()
- if err != nil {
- return "", errors.Wrapf(err, "neither XDG_RUNTIME_DIR nor HOME was set non-empty")
- }
- home = usr.HomeDir
- }
- return home, nil
-}
diff --git a/vendor/github.com/docker/spdystream/connection.go b/vendor/github.com/docker/spdystream/connection.go
index 2023ecf84..6031a0db1 100644
--- a/vendor/github.com/docker/spdystream/connection.go
+++ b/vendor/github.com/docker/spdystream/connection.go
@@ -14,7 +14,7 @@ import (
var (
ErrInvalidStreamId = errors.New("Invalid stream id")
- ErrTimeout = errors.New("Timeout occurred")
+ ErrTimeout = errors.New("Timeout occured")
ErrReset = errors.New("Stream reset")
ErrWriteClosedStream = errors.New("Write on closed stream")
)
@@ -325,7 +325,7 @@ Loop:
readFrame, err := s.framer.ReadFrame()
if err != nil {
if err != io.EOF {
- debugMessage("frame read error: %s", err)
+ fmt.Errorf("frame read error: %s", err)
} else {
debugMessage("(%p) EOF received", s)
}
@@ -421,7 +421,7 @@ func (s *Connection) frameHandler(frameQueue *PriorityFrameQueue, newHandler Str
}
if frameErr != nil {
- debugMessage("frame handling error: %s", frameErr)
+ fmt.Errorf("frame handling error: %s", frameErr)
}
}
}
@@ -451,7 +451,6 @@ func (s *Connection) addStreamFrame(frame *spdy.SynStreamFrame) {
dataChan: make(chan []byte),
headerChan: make(chan http.Header),
closeChan: make(chan bool),
- priority: frame.Priority,
}
if frame.CFHeader.Flags&spdy.ControlFlagFin != 0x00 {
stream.closeRemoteChannels()
@@ -474,7 +473,7 @@ func (s *Connection) checkStreamFrame(frame *spdy.SynStreamFrame) bool {
go func() {
resetErr := s.sendResetFrame(spdy.ProtocolError, frame.StreamId)
if resetErr != nil {
- debugMessage("reset error: %s", resetErr)
+ fmt.Errorf("reset error: %s", resetErr)
}
}()
return false
@@ -719,7 +718,7 @@ func (s *Connection) shutdown(closeTimeout time.Duration) {
select {
case err, ok := <-s.shutdownChan:
if ok {
- debugMessage("Unhandled close error after %s: %s", duration, err)
+ fmt.Errorf("Unhandled close error after %s: %s", duration, err)
}
default:
}
diff --git a/vendor/github.com/docker/spdystream/handlers.go b/vendor/github.com/docker/spdystream/handlers.go
index d4ee7be81..b59fa5fdc 100644
--- a/vendor/github.com/docker/spdystream/handlers.go
+++ b/vendor/github.com/docker/spdystream/handlers.go
@@ -30,7 +30,9 @@ func MirrorStreamHandler(stream *Stream) {
}()
}
-// NoopStreamHandler does nothing when stream connects.
+// NoopStreamHandler does nothing when stream connects, most
+// likely used with RejectAuthHandler which will not allow any
+// streams to make it to the stream handler.
func NoOpStreamHandler(stream *Stream) {
stream.SendReply(http.Header{}, false)
}
diff --git a/vendor/github.com/fsouza/go-dockerclient/.golangci.yaml b/vendor/github.com/fsouza/go-dockerclient/.golangci.yaml
index aa3ab39e5..3a21b76f7 100644
--- a/vendor/github.com/fsouza/go-dockerclient/.golangci.yaml
+++ b/vendor/github.com/fsouza/go-dockerclient/.golangci.yaml
@@ -25,5 +25,6 @@ linters:
- gochecknoglobals
- gocognit
- goconst
+ - gomnd
- lll
- wsl
diff --git a/vendor/github.com/fsouza/go-dockerclient/.travis.yml b/vendor/github.com/fsouza/go-dockerclient/.travis.yml
index 060f9e6a8..dbd76b175 100644
--- a/vendor/github.com/fsouza/go-dockerclient/.travis.yml
+++ b/vendor/github.com/fsouza/go-dockerclient/.travis.yml
@@ -3,6 +3,7 @@ language: go
go:
- 1.12.x
- 1.13.x
+ - 1.14rc1
os:
- linux
- osx
diff --git a/vendor/github.com/fsouza/go-dockerclient/AUTHORS b/vendor/github.com/fsouza/go-dockerclient/AUTHORS
index 663410f95..08f89afde 100644
--- a/vendor/github.com/fsouza/go-dockerclient/AUTHORS
+++ b/vendor/github.com/fsouza/go-dockerclient/AUTHORS
@@ -139,6 +139,7 @@ Michal Fojtik
Mike Dillon
Mrunal Patel
Nate Jones
+Nathan Pemberton
Nguyen Sy Thanh Son
Nicholas Van Wiggeren
Nick Ethier
diff --git a/vendor/github.com/fsouza/go-dockerclient/LICENSE b/vendor/github.com/fsouza/go-dockerclient/LICENSE
index 80d56fc05..7a70a8c40 100644
--- a/vendor/github.com/fsouza/go-dockerclient/LICENSE
+++ b/vendor/github.com/fsouza/go-dockerclient/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2019, go-dockerclient authors
+Copyright (c) 2013-2020, go-dockerclient authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/vendor/github.com/fsouza/go-dockerclient/README.md b/vendor/github.com/fsouza/go-dockerclient/README.md
index f4ad8ca62..d1128335d 100644
--- a/vendor/github.com/fsouza/go-dockerclient/README.md
+++ b/vendor/github.com/fsouza/go-dockerclient/README.md
@@ -2,7 +2,7 @@
[![Travis Build Status](https://travis-ci.com/fsouza/go-dockerclient.svg?branch=master)](https://travis-ci.com/fsouza/go-dockerclient)
[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/4yusq1f9dqbicobt?svg=true)](https://ci.appveyor.com/project/fsouza/go-dockerclient)
-[![GoDoc](https://img.shields.io/badge/api-Godoc-blue.svg?style=flat-square)](https://godoc.org/github.com/fsouza/go-dockerclient)
+[![GoDoc](https://img.shields.io/badge/api-Godoc-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/docker/docker/api/types?tab=doc#AuthConfig)
This package presents a client for the Docker remote API. It also provides
support for the extensions in the [Swarm API](https://docs.docker.com/swarm/swarm-api/).
diff --git a/vendor/github.com/fsouza/go-dockerclient/appveyor.yml b/vendor/github.com/fsouza/go-dockerclient/appveyor.yml
index e1574cfc2..f36478a5d 100644
--- a/vendor/github.com/fsouza/go-dockerclient/appveyor.yml
+++ b/vendor/github.com/fsouza/go-dockerclient/appveyor.yml
@@ -7,8 +7,9 @@ environment:
GOPROXY: https://proxy.golang.org
GO111MODULE: on
matrix:
- - GOVERSION: "1.12.13"
- - GOVERSION: "1.13.4"
+ - GOVERSION: "1.12.17"
+ - GOVERSION: "1.13.8"
+ - GOVERSION: "1.14rc1"
install:
- choco install make
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
diff --git a/vendor/github.com/fsouza/go-dockerclient/auth.go b/vendor/github.com/fsouza/go-dockerclient/auth.go
index eb1a31716..cae2a020f 100644
--- a/vendor/github.com/fsouza/go-dockerclient/auth.go
+++ b/vendor/github.com/fsouza/go-dockerclient/auth.go
@@ -30,7 +30,7 @@ type AuthConfiguration struct {
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken can be supplied with the identitytoken response of the AuthCheck call
- // see https://godoc.org/github.com/docker/docker/api/types#AuthConfig
+ // see https://pkg.go.dev/github.com/docker/docker/api/types?tab=doc#AuthConfig
// It can be used in place of password not in conjunction with it
IdentityToken string `json:"identitytoken,omitempty"`
@@ -170,9 +170,14 @@ func authConfigs(confs map[string]dockerConfig) (*AuthConfigurations, error) {
if conf.Auth == "" {
continue
}
+
+ // support both padded and unpadded encoding
data, err := base64.StdEncoding.DecodeString(conf.Auth)
if err != nil {
- return nil, err
+ data, err = base64.StdEncoding.WithPadding(base64.NoPadding).DecodeString(conf.Auth)
+ }
+ if err != nil {
+ return nil, errors.New("error decoding plaintext credentials")
}
userpass := strings.SplitN(string(data), ":", 2)
diff --git a/vendor/github.com/fsouza/go-dockerclient/container.go b/vendor/github.com/fsouza/go-dockerclient/container.go
index f6bfb59dc..309955fd5 100644
--- a/vendor/github.com/fsouza/go-dockerclient/container.go
+++ b/vendor/github.com/fsouza/go-dockerclient/container.go
@@ -730,6 +730,15 @@ type Device struct {
CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty" toml:"CgroupPermissions,omitempty"`
}
+// A list of requests for devices to be sent to device drivers
+type DeviceRequest struct {
+ Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty" toml:"Driver,omitempty"`
+ Count int `json:"Count,omitempty" yaml:"Count,omitempty" toml:"Count,omitempty"`
+ DeviceIDs []string `json:"DeviceIDs,omitempty" yaml:"DeviceIDs,omitempty" toml:"DeviceIDs,omitempty"`
+ Capabilities [][]string `json:"Capabilities,omitempty" yaml:"Capabilities,omitempty" toml:"Capabilities,omitempty"`
+ Options map[string]string `json:"Options,omitempty" yaml:"Options,omitempty" toml:"Options,omitempty"`
+}
+
// BlockWeight represents a relative device weight for an individual device inside
// of a container
type BlockWeight struct {
@@ -771,6 +780,7 @@ type HostConfig struct {
RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty" toml:"RestartPolicy,omitempty"`
Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"`
DeviceCgroupRules []string `json:"DeviceCgroupRules,omitempty" yaml:"DeviceCgroupRules,omitempty" toml:"DeviceCgroupRules,omitempty"`
+ DeviceRequests []DeviceRequest `json:"DeviceRequests,omitempty" yaml:"DeviceRequests,omitempty" toml:"DeviceRequests,omitempty"`
LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty" toml:"LogConfig,omitempty"`
SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty" toml:"SecurityOpt,omitempty"`
CgroupnsMode string `json:"CgroupnsMode,omitempty" yaml:"CgroupnsMode,omitempty" toml:"CgroupnsMode,omitempty"` // v1.40+
@@ -788,6 +798,7 @@ type HostConfig struct {
CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty" toml:"CpuPeriod,omitempty"`
CPURealtimePeriod int64 `json:"CpuRealtimePeriod,omitempty" yaml:"CpuRealtimePeriod,omitempty" toml:"CpuRealtimePeriod,omitempty"`
CPURealtimeRuntime int64 `json:"CpuRealtimeRuntime,omitempty" yaml:"CpuRealtimeRuntime,omitempty" toml:"CpuRealtimeRuntime,omitempty"`
+ NanoCPUs int64 `json:"NanoCpus,omitempty" yaml:"NanoCpus,omitempty" toml:"NanoCpus,omitempty"`
BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight,omitempty" toml:"BlkioWeight,omitempty"`
BlkioWeightDevice []BlockWeight `json:"BlkioWeightDevice,omitempty" yaml:"BlkioWeightDevice,omitempty" toml:"BlkioWeightDevice,omitempty"`
BlkioDeviceReadBps []BlockLimit `json:"BlkioDeviceReadBps,omitempty" yaml:"BlkioDeviceReadBps,omitempty" toml:"BlkioDeviceReadBps,omitempty"`
diff --git a/vendor/github.com/fsouza/go-dockerclient/go.mod b/vendor/github.com/fsouza/go-dockerclient/go.mod
index 7bb88972c..37ddd03c2 100644
--- a/vendor/github.com/fsouza/go-dockerclient/go.mod
+++ b/vendor/github.com/fsouza/go-dockerclient/go.mod
@@ -11,12 +11,12 @@ require (
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0
- github.com/google/go-cmp v0.3.1
- github.com/gorilla/mux v1.7.3
+ github.com/google/go-cmp v0.4.0
+ github.com/gorilla/mux v1.7.4
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect
- golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad
+ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
google.golang.org/grpc v1.22.0 // indirect
)
diff --git a/vendor/github.com/fsouza/go-dockerclient/go.sum b/vendor/github.com/fsouza/go-dockerclient/go.sum
index ce78fee7a..6fcd9b008 100644
--- a/vendor/github.com/fsouza/go-dockerclient/go.sum
+++ b/vendor/github.com/fsouza/go-dockerclient/go.sum
@@ -41,10 +41,10 @@ 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/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
-github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
+github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
@@ -84,8 +84,8 @@ go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-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-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -119,6 +119,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
diff --git a/vendor/github.com/fsouza/go-dockerclient/swarm_service.go b/vendor/github.com/fsouza/go-dockerclient/swarm_service.go
index cedbe41e3..4accb2cb8 100644
--- a/vendor/github.com/fsouza/go-dockerclient/swarm_service.go
+++ b/vendor/github.com/fsouza/go-dockerclient/swarm_service.go
@@ -147,6 +147,7 @@ func (c *Client) InspectService(id string) (*swarm.Service, error) {
// See https://goo.gl/DwvNMd for more details.
type ListServicesOptions struct {
Filters map[string][]string
+ Status bool
Context context.Context
}
diff --git a/vendor/github.com/fsouza/go-dockerclient/tls.go b/vendor/github.com/fsouza/go-dockerclient/tls.go
index 08e7f8ec2..8a76f0dbf 100644
--- a/vendor/github.com/fsouza/go-dockerclient/tls.go
+++ b/vendor/github.com/fsouza/go-dockerclient/tls.go
@@ -106,7 +106,6 @@ func copyTLSConfig(cfg *tls.Config) *tls.Config {
InsecureSkipVerify: cfg.InsecureSkipVerify, //nolint:gosec
MaxVersion: cfg.MaxVersion,
MinVersion: cfg.MinVersion,
- NameToCertificate: cfg.NameToCertificate,
NextProtos: cfg.NextProtos,
PreferServerCipherSuites: cfg.PreferServerCipherSuites,
Rand: cfg.Rand,
diff --git a/vendor/github.com/ishidawataru/sctp/.travis.yml b/vendor/github.com/ishidawataru/sctp/.travis.yml
index e72c57864..01a76be9a 100644
--- a/vendor/github.com/ishidawataru/sctp/.travis.yml
+++ b/vendor/github.com/ishidawataru/sctp/.travis.yml
@@ -1,10 +1,10 @@
language: go
go:
- - 1.6
- - 1.7
- - 1.8
- - 1.9
- - "1.10"
+ - 1.9.x
+ - 1.10.x
+ - 1.11.x
+ - 1.12.x
+ - 1.13.x
script:
- go test -v -race ./...
diff --git a/vendor/github.com/ishidawataru/sctp/NOTICE b/vendor/github.com/ishidawataru/sctp/NOTICE
new file mode 100644
index 000000000..cfb675fd4
--- /dev/null
+++ b/vendor/github.com/ishidawataru/sctp/NOTICE
@@ -0,0 +1,3 @@
+This source code includes following third party code
+
+- ipsock_linux.go : licensed by the Go authors, see GO_LICENSE file for the license which applies to the code
diff --git a/vendor/github.com/ishidawataru/sctp/go.mod b/vendor/github.com/ishidawataru/sctp/go.mod
new file mode 100644
index 000000000..5adf982b0
--- /dev/null
+++ b/vendor/github.com/ishidawataru/sctp/go.mod
@@ -0,0 +1,3 @@
+module github.com/ishidawataru/sctp
+
+go 1.12
diff --git a/vendor/github.com/ishidawataru/sctp/ipsock_linux.go b/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
index f5632b72d..3df30fa46 100644
--- a/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
+++ b/vendor/github.com/ishidawataru/sctp/ipsock_linux.go
@@ -1,3 +1,7 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the GO_LICENSE file.
+
package sctp
import (
diff --git a/vendor/github.com/ishidawataru/sctp/sctp.go b/vendor/github.com/ishidawataru/sctp/sctp.go
index 30d619640..94842f427 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp.go
@@ -1,3 +1,18 @@
+// Copyright 2019 Wataru Ishida. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package sctp
import (
@@ -678,3 +693,37 @@ func (c *SCTPSndRcvInfoWrappedConn) SetReadDeadline(t time.Time) error {
func (c *SCTPSndRcvInfoWrappedConn) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}
+
+func (c *SCTPSndRcvInfoWrappedConn) SetWriteBuffer(bytes int) error {
+ return c.conn.SetWriteBuffer(bytes)
+}
+
+func (c *SCTPSndRcvInfoWrappedConn) GetWriteBuffer() (int, error) {
+ return c.conn.GetWriteBuffer()
+}
+
+func (c *SCTPSndRcvInfoWrappedConn) SetReadBuffer(bytes int) error {
+ return c.conn.SetReadBuffer(bytes)
+}
+
+func (c *SCTPSndRcvInfoWrappedConn) GetReadBuffer() (int, error) {
+ return c.conn.GetReadBuffer()
+}
+
+// SocketConfig contains options for the SCTP socket.
+type SocketConfig struct {
+ // If Control is not nil it is called after the socket is created but before
+ // it is bound or connected.
+ Control func(network, address string, c syscall.RawConn) error
+
+ // InitMsg is the options to send in the initial SCTP message
+ InitMsg InitMsg
+}
+
+func (cfg *SocketConfig) Listen(net string, laddr *SCTPAddr) (*SCTPListener, error) {
+ return listenSCTPExtConfig(net, laddr, cfg.InitMsg, cfg.Control)
+}
+
+func (cfg *SocketConfig) Dial(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
+ return dialSCTPExtConfig(net, laddr, raddr, cfg.InitMsg, cfg.Control)
+}
diff --git a/vendor/github.com/ishidawataru/sctp/sctp_linux.go b/vendor/github.com/ishidawataru/sctp/sctp_linux.go
index 5a6ad9378..ac340ddfb 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp_linux.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp_linux.go
@@ -1,4 +1,18 @@
// +build linux,!386
+// Copyright 2019 Wataru Ishida. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package sctp
@@ -40,6 +54,23 @@ func getsockopt(fd int, optname, optval, optlen uintptr) (uintptr, uintptr, erro
return r0, r1, nil
}
+type rawConn struct {
+ sockfd int
+}
+
+func (r rawConn) Control(f func(fd uintptr)) error {
+ f(uintptr(r.sockfd))
+ return nil
+}
+
+func (r rawConn) Read(f func(fd uintptr) (done bool)) error {
+ panic("not implemented")
+}
+
+func (r rawConn) Write(f func(fd uintptr) (done bool)) error {
+ panic("not implemented")
+}
+
func (c *SCTPConn) SCTPWrite(b []byte, info *SndRcvInfo) (int, error) {
var cbuf []byte
if info != nil {
@@ -114,6 +145,22 @@ func (c *SCTPConn) Close() error {
return syscall.EBADF
}
+func (c *SCTPConn) SetWriteBuffer(bytes int) error {
+ return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
+}
+
+func (c *SCTPConn) GetWriteBuffer() (int, error) {
+ return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_SNDBUF)
+}
+
+func (c *SCTPConn) SetReadBuffer(bytes int) error {
+ return syscall.SetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
+}
+
+func (c *SCTPConn) GetReadBuffer() (int, error) {
+ return syscall.GetsockoptInt(c.fd(), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
+}
+
// ListenSCTP - start listener on specified address/port
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
return ListenSCTPExt(net, laddr, InitMsg{NumOstreams: SCTP_MAX_STREAM})
@@ -121,6 +168,11 @@ func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
// ListenSCTPExt - start listener on specified address/port with given SCTP options
func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListener, error) {
+ return listenSCTPExtConfig(network, laddr, options, nil)
+}
+
+// listenSCTPExtConfig - start listener on specified address/port with given SCTP options and socket configuration
+func listenSCTPExtConfig(network string, laddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPListener, error) {
af, ipv6only := favoriteAddrFamily(network, laddr, nil, "listen")
sock, err := syscall.Socket(
af,
@@ -140,6 +192,12 @@ func ListenSCTPExt(network string, laddr *SCTPAddr, options InitMsg) (*SCTPListe
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
return nil, err
}
+ if control != nil {
+ rc := rawConn{sockfd: sock}
+ if err = control(network, laddr.String(), rc); err != nil {
+ return nil, err
+ }
+ }
err = setInitOpts(sock, options)
if err != nil {
return nil, err
@@ -191,6 +249,11 @@ func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
// DialSCTPExt - same as DialSCTP but with given SCTP options
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
+ return dialSCTPExtConfig(network, laddr, raddr, options, nil)
+}
+
+// dialSCTPExtConfig - same as DialSCTP but with given SCTP options and socket configuration
+func dialSCTPExtConfig(network string, laddr, raddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPConn, error) {
af, ipv6only := favoriteAddrFamily(network, laddr, raddr, "dial")
sock, err := syscall.Socket(
af,
@@ -210,6 +273,12 @@ func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTP
if err = setDefaultSockopts(sock, af, ipv6only); err != nil {
return nil, err
}
+ if control != nil {
+ rc := rawConn{sockfd: sock}
+ if err = control(network, laddr.String(), rc); err != nil {
+ return nil, err
+ }
+ }
err = setInitOpts(sock, options)
if err != nil {
return nil, err
diff --git a/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go b/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
index e5415843d..118fe159e 100644
--- a/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
+++ b/vendor/github.com/ishidawataru/sctp/sctp_unsupported.go
@@ -1,4 +1,18 @@
// +build !linux linux,386
+// Copyright 2019 Wataru Ishida. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package sctp
@@ -6,6 +20,7 @@ import (
"errors"
"net"
"runtime"
+ "syscall"
)
var ErrUnsupported = errors.New("SCTP is unsupported on " + runtime.GOOS + "/" + runtime.GOARCH)
@@ -30,6 +45,22 @@ func (c *SCTPConn) Close() error {
return ErrUnsupported
}
+func (c *SCTPConn) SetWriteBuffer(bytes int) error {
+ return ErrUnsupported
+}
+
+func (c *SCTPConn) GetWriteBuffer() (int, error) {
+ return 0, ErrUnsupported
+}
+
+func (c *SCTPConn) SetReadBuffer(bytes int) error {
+ return ErrUnsupported
+}
+
+func (c *SCTPConn) GetReadBuffer() (int, error) {
+ return 0, ErrUnsupported
+}
+
func ListenSCTP(net string, laddr *SCTPAddr) (*SCTPListener, error) {
return nil, ErrUnsupported
}
@@ -38,6 +69,10 @@ func ListenSCTPExt(net string, laddr *SCTPAddr, options InitMsg) (*SCTPListener,
return nil, ErrUnsupported
}
+func listenSCTPExtConfig(network string, laddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPListener, error) {
+ return nil, ErrUnsupported
+}
+
func (ln *SCTPListener) Accept() (net.Conn, error) {
return nil, ErrUnsupported
}
@@ -57,3 +92,7 @@ func DialSCTP(net string, laddr, raddr *SCTPAddr) (*SCTPConn, error) {
func DialSCTPExt(network string, laddr, raddr *SCTPAddr, options InitMsg) (*SCTPConn, error) {
return nil, ErrUnsupported
}
+
+func dialSCTPExtConfig(network string, laddr, raddr *SCTPAddr, options InitMsg, control func(network, address string, c syscall.RawConn) error) (*SCTPConn, error) {
+ return nil, ErrUnsupported
+}
diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
index b0a470f92..3d2fdcd77 100644
--- a/vendor/github.com/klauspost/compress/flate/fast_encoder.go
+++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
@@ -42,10 +42,10 @@ const (
baseMatchLength = 3 // The smallest match length per the RFC section 3.2.5
maxMatchOffset = 1 << 15 // The largest match offset
- bTableBits = 18 // Bits used in the big tables
- bTableSize = 1 << bTableBits // Size of the table
- allocHistory = maxMatchOffset * 10 // Size to preallocate for history.
- bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize // Reset the buffer offset when reaching this.
+ bTableBits = 18 // Bits used in the big tables
+ bTableSize = 1 << bTableBits // Size of the table
+ allocHistory = maxStoreBlockSize * 20 // Size to preallocate for history.
+ bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize - 1 // Reset the buffer offset when reaching this.
)
const (
@@ -210,16 +210,14 @@ func (e *fastGen) matchlenLong(s, t int32, src []byte) int32 {
// Reset the encoding table.
func (e *fastGen) Reset() {
- if cap(e.hist) < int(maxMatchOffset*8) {
- l := maxMatchOffset * 8
- // Make it at least 1MB.
- if l < 1<<20 {
- l = 1 << 20
- }
- e.hist = make([]byte, 0, l)
+ if cap(e.hist) < allocHistory {
+ e.hist = make([]byte, 0, allocHistory)
+ }
+ // We offset current position so everything will be out of reach.
+ // If we are above the buffer reset it will be cleared anyway since len(hist) == 0.
+ if e.cur <= bufferReset {
+ e.cur += maxMatchOffset + int32(len(e.hist))
}
- // We offset current position so everything will be out of reach
- e.cur += maxMatchOffset + int32(len(e.hist))
e.hist = e.hist[:0]
}
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
index 9feea87a3..56ee6dc8b 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
@@ -177,6 +177,11 @@ func (w *huffmanBitWriter) flush() {
w.nbits = 0
return
}
+ if w.lastHeader > 0 {
+ // We owe an EOB
+ w.writeCode(w.literalEncoding.codes[endBlockMarker])
+ w.lastHeader = 0
+ }
n := w.nbytes
for w.nbits != 0 {
w.bytes[n] = byte(w.bits)
@@ -594,8 +599,8 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b
tokens.AddEOB()
}
- // We cannot reuse pure huffman table.
- if w.lastHuffMan && w.lastHeader > 0 {
+ // We cannot reuse pure huffman table, and must mark as EOF.
+ if (w.lastHuffMan || eof) && w.lastHeader > 0 {
// We will not try to reuse.
w.writeCode(w.literalEncoding.codes[endBlockMarker])
w.lastHeader = 0
diff --git a/vendor/github.com/klauspost/compress/flate/level1.go b/vendor/github.com/klauspost/compress/flate/level1.go
index 20de8f11f..102fc74c7 100644
--- a/vendor/github.com/klauspost/compress/flate/level1.go
+++ b/vendor/github.com/klauspost/compress/flate/level1.go
@@ -1,5 +1,7 @@
package flate
+import "fmt"
+
// fastGen maintains the table for matches,
// and the previous byte block for level 2.
// This is the generic implementation.
@@ -14,6 +16,9 @@ func (e *fastEncL1) Encode(dst *tokens, src []byte) {
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
diff --git a/vendor/github.com/klauspost/compress/flate/level2.go b/vendor/github.com/klauspost/compress/flate/level2.go
index 7c824431e..dc6b1d314 100644
--- a/vendor/github.com/klauspost/compress/flate/level2.go
+++ b/vendor/github.com/klauspost/compress/flate/level2.go
@@ -1,5 +1,7 @@
package flate
+import "fmt"
+
// fastGen maintains the table for matches,
// and the previous byte block for level 2.
// This is the generic implementation.
@@ -16,6 +18,10 @@ func (e *fastEncL2) Encode(dst *tokens, src []byte) {
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
+
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
if len(e.hist) == 0 {
diff --git a/vendor/github.com/klauspost/compress/flate/level3.go b/vendor/github.com/klauspost/compress/flate/level3.go
index 4153d24c9..1a3ff9b6b 100644
--- a/vendor/github.com/klauspost/compress/flate/level3.go
+++ b/vendor/github.com/klauspost/compress/flate/level3.go
@@ -1,5 +1,7 @@
package flate
+import "fmt"
+
// fastEncL3
type fastEncL3 struct {
fastGen
@@ -13,6 +15,10 @@ func (e *fastEncL3) Encode(dst *tokens, src []byte) {
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
+
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
if len(e.hist) == 0 {
diff --git a/vendor/github.com/klauspost/compress/flate/level4.go b/vendor/github.com/klauspost/compress/flate/level4.go
index c689ac771..f3ecc9c4d 100644
--- a/vendor/github.com/klauspost/compress/flate/level4.go
+++ b/vendor/github.com/klauspost/compress/flate/level4.go
@@ -13,7 +13,9 @@ func (e *fastEncL4) Encode(dst *tokens, src []byte) {
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
-
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
if len(e.hist) == 0 {
diff --git a/vendor/github.com/klauspost/compress/flate/level5.go b/vendor/github.com/klauspost/compress/flate/level5.go
index 14a235612..4e3916825 100644
--- a/vendor/github.com/klauspost/compress/flate/level5.go
+++ b/vendor/github.com/klauspost/compress/flate/level5.go
@@ -13,6 +13,9 @@ func (e *fastEncL5) Encode(dst *tokens, src []byte) {
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
diff --git a/vendor/github.com/klauspost/compress/flate/level6.go b/vendor/github.com/klauspost/compress/flate/level6.go
index cad0c7df7..00a311977 100644
--- a/vendor/github.com/klauspost/compress/flate/level6.go
+++ b/vendor/github.com/klauspost/compress/flate/level6.go
@@ -13,6 +13,9 @@ func (e *fastEncL6) Encode(dst *tokens, src []byte) {
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
+ if debugDecode && e.cur < 0 {
+ panic(fmt.Sprint("e.cur < 0: ", e.cur))
+ }
// Protect against e.cur wraparound.
for e.cur >= bufferReset {
diff --git a/vendor/github.com/klauspost/compress/flate/stateless.go b/vendor/github.com/klauspost/compress/flate/stateless.go
index a47051197..53e899124 100644
--- a/vendor/github.com/klauspost/compress/flate/stateless.go
+++ b/vendor/github.com/klauspost/compress/flate/stateless.go
@@ -8,6 +8,8 @@ import (
const (
maxStatelessBlock = math.MaxInt16
+ // dictionary will be taken from maxStatelessBlock, so limit it.
+ maxStatelessDict = 8 << 10
slTableBits = 13
slTableSize = 1 << slTableBits
@@ -25,11 +27,11 @@ func (s *statelessWriter) Close() error {
}
s.closed = true
// Emit EOF block
- return StatelessDeflate(s.dst, nil, true)
+ return StatelessDeflate(s.dst, nil, true, nil)
}
func (s *statelessWriter) Write(p []byte) (n int, err error) {
- err = StatelessDeflate(s.dst, p, false)
+ err = StatelessDeflate(s.dst, p, false, nil)
if err != nil {
return 0, err
}
@@ -59,7 +61,10 @@ var bitWriterPool = sync.Pool{
// StatelessDeflate allows to compress directly to a Writer without retaining state.
// When returning everything will be flushed.
-func StatelessDeflate(out io.Writer, in []byte, eof bool) error {
+// Up to 8KB of an optional dictionary can be given which is presumed to presumed to precede the block.
+// Longer dictionaries will be truncated and will still produce valid output.
+// Sending nil dictionary is perfectly fine.
+func StatelessDeflate(out io.Writer, in []byte, eof bool, dict []byte) error {
var dst tokens
bw := bitWriterPool.Get().(*huffmanBitWriter)
bw.reset(out)
@@ -76,35 +81,53 @@ func StatelessDeflate(out io.Writer, in []byte, eof bool) error {
return bw.err
}
+ // Truncate dict
+ if len(dict) > maxStatelessDict {
+ dict = dict[len(dict)-maxStatelessDict:]
+ }
+
for len(in) > 0 {
todo := in
- if len(todo) > maxStatelessBlock {
- todo = todo[:maxStatelessBlock]
+ if len(todo) > maxStatelessBlock-len(dict) {
+ todo = todo[:maxStatelessBlock-len(dict)]
}
in = in[len(todo):]
+ uncompressed := todo
+ if len(dict) > 0 {
+ // combine dict and source
+ bufLen := len(todo) + len(dict)
+ combined := make([]byte, bufLen)
+ copy(combined, dict)
+ copy(combined[len(dict):], todo)
+ todo = combined
+ }
// Compress
- statelessEnc(&dst, todo)
+ statelessEnc(&dst, todo, int16(len(dict)))
isEof := eof && len(in) == 0
if dst.n == 0 {
- bw.writeStoredHeader(len(todo), isEof)
+ bw.writeStoredHeader(len(uncompressed), isEof)
if bw.err != nil {
return bw.err
}
- bw.writeBytes(todo)
- } else if int(dst.n) > len(todo)-len(todo)>>4 {
+ bw.writeBytes(uncompressed)
+ } else if int(dst.n) > len(uncompressed)-len(uncompressed)>>4 {
// If we removed less than 1/16th, huffman compress the block.
- bw.writeBlockHuff(isEof, todo, false)
+ bw.writeBlockHuff(isEof, uncompressed, len(in) == 0)
} else {
- bw.writeBlockDynamic(&dst, isEof, todo, false)
+ bw.writeBlockDynamic(&dst, isEof, uncompressed, len(in) == 0)
+ }
+ if len(in) > 0 {
+ // Retain a dict if we have more
+ dict = todo[len(todo)-maxStatelessDict:]
+ dst.Reset()
}
if bw.err != nil {
return bw.err
}
- dst.Reset()
}
if !eof {
- // Align.
+ // Align, only a stored block can do that.
bw.writeStoredHeader(0, false)
}
bw.flush()
@@ -130,7 +153,7 @@ func load6416(b []byte, i int16) uint64 {
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
-func statelessEnc(dst *tokens, src []byte) {
+func statelessEnc(dst *tokens, src []byte, startAt int16) {
const (
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
@@ -144,15 +167,23 @@ func statelessEnc(dst *tokens, src []byte) {
// This check isn't in the Snappy implementation, but there, the caller
// instead of the callee handles this case.
- if len(src) < minNonLiteralBlockSize {
+ if len(src)-int(startAt) < minNonLiteralBlockSize {
// We do not fill the token table.
// This will be picked up by caller.
- dst.n = uint16(len(src))
+ dst.n = 0
return
}
+ // Index until startAt
+ if startAt > 0 {
+ cv := load3232(src, 0)
+ for i := int16(0); i < startAt; i++ {
+ table[hashSL(cv)] = tableEntry{offset: i}
+ cv = (cv >> 8) | (uint32(src[i+4]) << 24)
+ }
+ }
- s := int16(1)
- nextEmit := int16(0)
+ s := startAt + 1
+ nextEmit := startAt
// sLimit is when to stop looking for offset/length copies. The inputMargin
// lets us use a fast path for emitLiteral in the main loop, while we are
// looking for copies.
diff --git a/vendor/github.com/mattn/go-shellwords/util_go15.go b/vendor/github.com/mattn/go-shellwords/util_go15.go
deleted file mode 100644
index ddcbf229e..000000000
--- a/vendor/github.com/mattn/go-shellwords/util_go15.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// +build !go1.6
-
-package shellwords
-
-import (
- "os"
- "os/exec"
- "runtime"
- "strings"
-)
-
-func shellRun(line, dir string) (string, error) {
- var b []byte
- var err error
- var cmd *exec.Cmd
- if runtime.GOOS == "windows" {
- cmd = exec.Command(os.Getenv("COMSPEC"), "/c", line)
- } else {
- cmd = exec.Command(os.Getenv("SHELL"), "-c", line)
- }
- if dir != "" {
- cmd.Dir = dir
- }
- b, err = cmd.Output()
- if err != nil {
- return "", err
- }
- return strings.TrimSpace(string(b)), nil
-}
diff --git a/vendor/github.com/mattn/go-shellwords/util_posix.go b/vendor/github.com/mattn/go-shellwords/util_posix.go
index 3aef2c4d7..988fc9ed2 100644
--- a/vendor/github.com/mattn/go-shellwords/util_posix.go
+++ b/vendor/github.com/mattn/go-shellwords/util_posix.go
@@ -1,4 +1,4 @@
-// +build !windows,go1.6
+// +build !windows
package shellwords
@@ -10,7 +10,10 @@ import (
)
func shellRun(line, dir string) (string, error) {
- shell := os.Getenv("SHELL")
+ var shell string
+ if shell = os.Getenv("SHELL"); shell == "" {
+ shell = "/bin/sh"
+ }
cmd := exec.Command(shell, "-c", line)
if dir != "" {
cmd.Dir = dir
diff --git a/vendor/github.com/mattn/go-shellwords/util_windows.go b/vendor/github.com/mattn/go-shellwords/util_windows.go
index cda685091..20546737c 100644
--- a/vendor/github.com/mattn/go-shellwords/util_windows.go
+++ b/vendor/github.com/mattn/go-shellwords/util_windows.go
@@ -1,4 +1,4 @@
-// +build windows,go1.6
+// +build windows
package shellwords
@@ -10,7 +10,10 @@ import (
)
func shellRun(line, dir string) (string, error) {
- shell := os.Getenv("COMSPEC")
+ var shell string
+ if shell = os.Getenv("COMSPEC"); shell == "" {
+ shell = "cmd"
+ }
cmd := exec.Command(shell, "/c", line)
if dir != "" {
cmd.Dir = dir
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index 9fcfd0867..0e97a0778 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -11,6 +11,7 @@ import (
"io"
"io/ioutil"
"os"
+ "path"
"path/filepath"
"regexp"
"strconv"
@@ -37,15 +38,14 @@ const (
selinuxTag = "SELINUX"
xattrNameSelinux = "security.selinux"
stRdOnly = 0x01
- selinuxfsMagic = 0xf97cff8c
)
type selinuxState struct {
- enabledSet bool
- enabled bool
- selinuxfsSet bool
- selinuxfs string
- mcsList map[string]bool
+ enabledSet bool
+ enabled bool
+ selinuxfsOnce sync.Once
+ selinuxfs string
+ mcsList map[string]bool
sync.Mutex
}
@@ -62,6 +62,10 @@ var (
state = selinuxState{
mcsList: make(map[string]bool),
}
+
+ // for attrPath()
+ attrPathOnce sync.Once
+ haveThreadSelf bool
)
// Context is a representation of the SELinux label broken into 4 parts
@@ -98,14 +102,6 @@ func SetDisabled() {
state.setEnable(false)
}
-func (s *selinuxState) setSELinuxfs(selinuxfs string) string {
- s.Lock()
- defer s.Unlock()
- s.selinuxfsSet = true
- s.selinuxfs = selinuxfs
- return s.selinuxfs
-}
-
func verifySELinuxfsMount(mnt string) bool {
var buf syscall.Statfs_t
for {
@@ -118,7 +114,8 @@ func verifySELinuxfsMount(mnt string) bool {
}
return false
}
- if uint32(buf.Type) != uint32(selinuxfsMagic) {
+
+ if buf.Type != unix.SELINUX_MAGIC {
return false
}
if (buf.Flags & stRdOnly) != 0 {
@@ -166,33 +163,29 @@ func findSELinuxfs() string {
// if there is one, or an empty string in case of EOF or error.
func findSELinuxfsMount(s *bufio.Scanner) string {
for s.Scan() {
- txt := s.Text()
+ txt := s.Bytes()
// The first field after - is fs type.
// Safe as spaces in mountpoints are encoded as \040
- if !strings.Contains(txt, " - selinuxfs ") {
+ if !bytes.Contains(txt, []byte(" - selinuxfs ")) {
continue
}
const mPos = 5 // mount point is 5th field
- fields := strings.SplitN(txt, " ", mPos+1)
+ fields := bytes.SplitN(txt, []byte(" "), mPos+1)
if len(fields) < mPos+1 {
continue
}
- return fields[mPos-1]
+ return string(fields[mPos-1])
}
return ""
}
func (s *selinuxState) getSELinuxfs() string {
- s.Lock()
- selinuxfs := s.selinuxfs
- selinuxfsSet := s.selinuxfsSet
- s.Unlock()
- if selinuxfsSet {
- return selinuxfs
- }
+ s.selinuxfsOnce.Do(func() {
+ s.selinuxfs = findSELinuxfs()
+ })
- return s.setSELinuxfs(findSELinuxfs())
+ return s.selinuxfs
}
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
@@ -254,10 +247,17 @@ func getSELinuxPolicyRoot() string {
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
}
-func isProcHandle(fh *os.File) (bool, error) {
+func isProcHandle(fh *os.File) error {
var buf unix.Statfs_t
err := unix.Fstatfs(int(fh.Fd()), &buf)
- return buf.Type == unix.PROC_SUPER_MAGIC, err
+ if err != nil {
+ return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err)
+ }
+ if buf.Type != unix.PROC_SUPER_MAGIC {
+ return fmt.Errorf("file %q is not on procfs", fh.Name())
+ }
+
+ return nil
}
func readCon(fpath string) (string, error) {
@@ -271,10 +271,8 @@ func readCon(fpath string) (string, error) {
}
defer in.Close()
- if ok, err := isProcHandle(in); err != nil {
+ if err := isProcHandle(in); err != nil {
return "", err
- } else if !ok {
- return "", fmt.Errorf("%s not on procfs", fpath)
}
var retval string
@@ -317,7 +315,7 @@ SetFSCreateLabel tells kernel the label to create all file system objects
created by this task. Setting label="" to return to default.
*/
func SetFSCreateLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), label)
+ return writeAttr("fscreate", label)
}
/*
@@ -325,12 +323,12 @@ FSCreateLabel returns the default label the kernel which the kernel is using
for file system objects created by this task. "" indicates default.
*/
func FSCreateLabel() (string, error) {
- return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()))
+ return readAttr("fscreate")
}
// CurrentLabel returns the SELinux label of the current process thread, or an error.
func CurrentLabel() (string, error) {
- return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid()))
+ return readAttr("current")
}
// PidLabel returns the SELinux label of the given pid, or an error.
@@ -343,10 +341,10 @@ ExecLabel returns the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func ExecLabel() (string, error) {
- return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()))
+ return readAttr("exec")
}
-func writeCon(fpath string, val string) error {
+func writeCon(fpath, val string) error {
if fpath == "" {
return ErrEmptyPath
}
@@ -362,10 +360,8 @@ func writeCon(fpath string, val string) error {
}
defer out.Close()
- if ok, err := isProcHandle(out); err != nil {
+ if err := isProcHandle(out); err != nil {
return err
- } else if !ok {
- return fmt.Errorf("%s not on procfs", fpath)
}
if val != "" {
@@ -379,6 +375,32 @@ func writeCon(fpath string, val string) error {
return nil
}
+func attrPath(attr string) string {
+ // Linux >= 3.17 provides this
+ const threadSelfPrefix = "/proc/thread-self/attr"
+
+ attrPathOnce.Do(func() {
+ st, err := os.Stat(threadSelfPrefix)
+ if err == nil && st.Mode().IsDir() {
+ haveThreadSelf = true
+ }
+ })
+
+ if haveThreadSelf {
+ return path.Join(threadSelfPrefix, attr)
+ }
+
+ return path.Join("/proc/self/task/", strconv.Itoa(syscall.Gettid()), "/attr/", attr)
+}
+
+func readAttr(attr string) (string, error) {
+ return readCon(attrPath(attr))
+}
+
+func writeAttr(attr, val string) error {
+ return writeCon(attrPath(attr), val)
+}
+
/*
CanonicalizeContext takes a context string and writes it to the kernel
the function then returns the context that the kernel will use. This function
@@ -415,7 +437,7 @@ SetExecLabel sets the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func SetExecLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), label)
+ return writeAttr("exec", label)
}
/*
@@ -423,18 +445,18 @@ SetTaskLabel sets the SELinux label for the current thread, or an error.
This requires the dyntransition permission.
*/
func SetTaskLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid()), label)
+ return writeAttr("current", label)
}
// SetSocketLabel takes a process label and tells the kernel to assign the
// label to the next socket that gets created
func SetSocketLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/sockcreate", syscall.Gettid()), label)
+ return writeAttr("sockcreate", label)
}
// SocketLabel retrieves the current socket label setting
func SocketLabel() (string, error) {
- return readCon(fmt.Sprintf("/proc/self/task/%d/attr/sockcreate", syscall.Gettid()))
+ return readAttr("sockcreate")
}
// PeerLabel retrieves the label of the client on the other side of a socket
@@ -449,7 +471,7 @@ func SetKeyLabel(label string) error {
if os.IsNotExist(err) {
return nil
}
- if label == "" && os.IsPermission(err) && !GetEnabled() {
+ if label == "" && os.IsPermission(err) {
return nil
}
return err
@@ -505,19 +527,18 @@ func ReserveLabel(label string) {
}
func selinuxEnforcePath() string {
- return fmt.Sprintf("%s/enforce", getSelinuxMountPoint())
+ return path.Join(getSelinuxMountPoint(), "enforce")
}
// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
var enforce int
- enforceS, err := readCon(selinuxEnforcePath())
+ enforceB, err := ioutil.ReadFile(selinuxEnforcePath())
if err != nil {
return -1
}
-
- enforce, err = strconv.Atoi(string(enforceS))
+ enforce, err = strconv.Atoi(string(enforceB))
if err != nil {
return -1
}
@@ -529,7 +550,7 @@ SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time.
*/
func SetEnforceMode(mode int) error {
- return writeCon(selinuxEnforcePath(), fmt.Sprintf("%d", mode))
+ return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
}
/*
@@ -711,7 +732,7 @@ exit:
// SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error {
- return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val)
+ return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
}
/*
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
index 67a9d8ee8..4e711a9f8 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
@@ -3,76 +3,32 @@
package selinux
import (
- "syscall"
- "unsafe"
+ "golang.org/x/sys/unix"
)
-var _zero uintptr
-
// Returns a []byte slice if the xattr is set and nil otherwise
// Requires path and its attribute as arguments
func lgetxattr(path string, attr string) ([]byte, error) {
- var sz int
- pathBytes, err := syscall.BytePtrFromString(path)
- if err != nil {
- return nil, err
- }
- attrBytes, err := syscall.BytePtrFromString(attr)
- if err != nil {
- return nil, err
- }
-
// Start with a 128 length byte array
- sz = 128
- dest := make([]byte, sz)
- destBytes := unsafe.Pointer(&dest[0])
- _sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
-
- switch {
- case errno == syscall.ENODATA:
- return nil, errno
- case errno == syscall.ENOTSUP:
- return nil, errno
- case errno == syscall.ERANGE:
- // 128 byte array might just not be good enough,
- // A dummy buffer is used ``uintptr(0)`` to get real size
- // of the xattrs on disk
- _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0)
- sz = int(_sz)
- if sz < 0 {
+ dest := make([]byte, 128)
+ sz, errno := unix.Lgetxattr(path, attr, dest)
+ if errno == unix.ERANGE {
+ // Buffer too small, get the real size first
+ sz, errno = unix.Lgetxattr(path, attr, []byte{})
+ if errno != nil {
return nil, errno
}
+
dest = make([]byte, sz)
- destBytes := unsafe.Pointer(&dest[0])
- _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
- if errno != 0 {
- return nil, errno
- }
- case errno != 0:
+ sz, errno = unix.Lgetxattr(path, attr, dest)
+ }
+ if errno != nil {
return nil, errno
}
- sz = int(_sz)
+
return dest[:sz], nil
}
func lsetxattr(path string, attr string, data []byte, flags int) error {
- pathBytes, err := syscall.BytePtrFromString(path)
- if err != nil {
- return err
- }
- attrBytes, err := syscall.BytePtrFromString(attr)
- if err != nil {
- return err
- }
- var dataBytes unsafe.Pointer
- if len(data) > 0 {
- dataBytes = unsafe.Pointer(&data[0])
- } else {
- dataBytes = unsafe.Pointer(&_zero)
- }
- _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
- if errno != 0 {
- return errno
- }
- return nil
+ return unix.Lsetxattr(path, attr, data, flags)
}
diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore
index 3b053c59e..b2b848e77 100644
--- a/vendor/github.com/spf13/cobra/.gitignore
+++ b/vendor/github.com/spf13/cobra/.gitignore
@@ -32,7 +32,8 @@ Session.vim
tags
*.exe
-
+cobra
cobra.test
-.idea/*
+.idea/
+*.iml
diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml
index 38b85f499..fca1e6948 100644
--- a/vendor/github.com/spf13/cobra/.travis.yml
+++ b/vendor/github.com/spf13/cobra/.travis.yml
@@ -18,13 +18,10 @@ matrix:
go: 1.12.x
script: diff -u <(echo -n) <(gofmt -d -s .)
-before_install:
- - mkdir -p bin
- - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.6.0/shellcheck
- - chmod +x bin/shellcheck
- - go get -u github.com/kyoh86/richgo
+before_install: go get -u github.com/kyoh86/richgo
+
script:
- - PATH=$PATH:$PWD/bin richgo test -v ./...
+ - richgo test -v ./...
- go build
- if [ -z $NOVET ]; then
diff -u <(echo -n) <(go vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint');
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index 60c5a425b..2f8175bc2 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -24,11 +24,13 @@ Many of the most widely used Go projects are built using Cobra, such as:
[Prototool](https://github.com/uber/prototool),
[mattermost-server](https://github.com/mattermost/mattermost-server),
[Gardener](https://github.com/gardener/gardenctl),
+[Linkerd](https://linkerd.io/),
etc.
[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra)
[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra)
+[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra)
# Table of Contents
@@ -208,51 +210,78 @@ You will additionally define flags and handle configuration in your init() funct
For example cmd/root.go:
```go
+package cmd
+
import (
- "fmt"
- "os"
+ "fmt"
+ "os"
- homedir "github.com/mitchellh/go-homedir"
- "github.com/spf13/cobra"
- "github.com/spf13/viper"
+ homedir "github.com/mitchellh/go-homedir"
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
)
-func init() {
- cobra.OnInitialize(initConfig)
- rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
- rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
- rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
- rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
- rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
- viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
- viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
- viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
- viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
- viper.SetDefault("license", "apache")
+var (
+ // Used for flags.
+ cfgFile string
+ userLicense string
+
+ rootCmd = &cobra.Command{
+ Use: "cobra",
+ Short: "A generator for Cobra based Applications",
+ Long: `Cobra is a CLI library for Go that empowers applications.
+This application is a tool to generate the needed files
+to quickly create a Cobra application.`,
+ }
+)
+
+// Execute executes the root command.
+func Execute() error {
+ return rootCmd.Execute()
}
-func initConfig() {
- // Don't forget to read config either from cfgFile or from home directory!
- if cfgFile != "" {
- // Use config file from the flag.
- viper.SetConfigFile(cfgFile)
- } else {
- // Find home directory.
- home, err := homedir.Dir()
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
+func init() {
+ cobra.OnInitialize(initConfig)
+
+ rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
+ rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
+ rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
+ rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
+ viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
+ viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
+ viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
+ viper.SetDefault("license", "apache")
+
+ rootCmd.AddCommand(addCmd)
+ rootCmd.AddCommand(initCmd)
+}
- // Search config in home directory with name ".cobra" (without extension).
- viper.AddConfigPath(home)
- viper.SetConfigName(".cobra")
- }
+func er(msg interface{}) {
+ fmt.Println("Error:", msg)
+ os.Exit(1)
+}
- if err := viper.ReadInConfig(); err != nil {
- fmt.Println("Can't read config:", err)
- os.Exit(1)
- }
+func initConfig() {
+ if cfgFile != "" {
+ // Use config file from the flag.
+ viper.SetConfigFile(cfgFile)
+ } else {
+ // Find home directory.
+ home, err := homedir.Dir()
+ if err != nil {
+ er(err)
+ }
+
+ // Search config in home directory with name ".cobra" (without extension).
+ viper.AddConfigPath(home)
+ viper.SetConfigName(".cobra")
+ }
+
+ viper.AutomaticEnv()
+
+ if err := viper.ReadInConfig(); err == nil {
+ fmt.Println("Using config file:", viper.ConfigFileUsed())
+ }
}
```
@@ -459,7 +488,7 @@ For many years people have printed back to the screen.`,
Echo works a lot like print, except it has a child command.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
- fmt.Println("Print: " + strings.Join(args, " "))
+ fmt.Println("Echo: " + strings.Join(args, " "))
},
}
diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go
index 57bb8e1b3..1e0e25cf6 100644
--- a/vendor/github.com/spf13/cobra/bash_completions.go
+++ b/vendor/github.com/spf13/cobra/bash_completions.go
@@ -61,6 +61,7 @@ __%[1]s_contains_word()
__%[1]s_handle_reply()
{
__%[1]s_debug "${FUNCNAME[0]}"
+ local comp
case $cur in
-*)
if [[ $(type -t compopt) = "builtin" ]]; then
@@ -72,7 +73,9 @@ __%[1]s_handle_reply()
else
allflags=("${flags[*]} ${two_word_flags[*]}")
fi
- COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
+ while IFS='' read -r comp; do
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${allflags[*]}" -- "$cur")
if [[ $(type -t compopt) = "builtin" ]]; then
[[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
fi
@@ -122,10 +125,14 @@ __%[1]s_handle_reply()
if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
completions+=("${must_have_one_flag[@]}")
fi
- COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
+ while IFS='' read -r comp; do
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${completions[*]}" -- "$cur")
if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
- COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") )
+ while IFS='' read -r comp; do
+ COMPREPLY+=("$comp")
+ done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
fi
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
@@ -160,7 +167,7 @@ __%[1]s_handle_filename_extension_flag()
__%[1]s_handle_subdirs_in_dir_flag()
{
local dir="$1"
- pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1
+ pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
}
__%[1]s_handle_flag()
diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go
index 6505c070b..d01becc8f 100644
--- a/vendor/github.com/spf13/cobra/cobra.go
+++ b/vendor/github.com/spf13/cobra/cobra.go
@@ -52,7 +52,7 @@ var EnableCommandSorting = true
// if the CLI is started from explorer.exe.
// To disable the mousetrap, just set this variable to blank string ("").
// Works only on Microsoft Windows.
-var MousetrapHelpText string = `This is a command line tool.
+var MousetrapHelpText = `This is a command line tool.
You need to open cmd.exe and run it from there.
`
@@ -61,7 +61,7 @@ You need to open cmd.exe and run it from there.
// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed.
// To disable the mousetrap, just set MousetrapHelpText to blank string ("").
// Works only on Microsoft Windows.
-var MousetrapDisplayDuration time.Duration = 5 * time.Second
+var MousetrapDisplayDuration = 5 * time.Second
// AddTemplateFunc adds a template function that's available to Usage and Help
// template generation.
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index c7e898303..fb60ebd93 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -17,6 +17,8 @@ package cobra
import (
"bytes"
+ "context"
+ "errors"
"fmt"
"io"
"os"
@@ -27,6 +29,8 @@ import (
flag "github.com/spf13/pflag"
)
+var ErrSubCommandRequired = errors.New("subcommand is required")
+
// FParseErrWhitelist configures Flag parse errors to be ignored
type FParseErrWhitelist flag.ParseErrorsWhitelist
@@ -140,9 +144,11 @@ type Command struct {
// TraverseChildren parses flags on all parents before executing child command.
TraverseChildren bool
- //FParseErrWhitelist flag parse errors to be ignored
+ // FParseErrWhitelist flag parse errors to be ignored
FParseErrWhitelist FParseErrWhitelist
+ ctx context.Context
+
// commands is the list of commands supported by this program.
commands []*Command
// parent is a parent command for this command.
@@ -202,6 +208,12 @@ type Command struct {
errWriter io.Writer
}
+// Context returns underlying command context. If command wasn't
+// executed with ExecuteContext Context returns Background context.
+func (c *Command) Context() context.Context {
+ return c.ctx
+}
+
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
// particularly useful when testing.
func (c *Command) SetArgs(a []string) {
@@ -228,7 +240,7 @@ func (c *Command) SetErr(newErr io.Writer) {
c.errWriter = newErr
}
-// SetOut sets the source for input data
+// SetIn sets the source for input data
// If newIn is nil, os.Stdin is used.
func (c *Command) SetIn(newIn io.Reader) {
c.inReader = newIn
@@ -297,7 +309,7 @@ func (c *Command) ErrOrStderr() io.Writer {
return c.getErr(os.Stderr)
}
-// ErrOrStderr returns output to stderr
+// InOrStdin returns output to stderr
func (c *Command) InOrStdin() io.Reader {
return c.getIn(os.Stdin)
}
@@ -369,6 +381,8 @@ func (c *Command) HelpFunc() func(*Command, []string) {
}
return func(c *Command, a []string) {
c.mergePersistentFlags()
+ // The help should be sent to stdout
+ // See https://github.com/spf13/cobra/issues/1002
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
if err != nil {
c.Println(err)
@@ -786,7 +800,7 @@ func (c *Command) execute(a []string) (err error) {
}
if !c.Runnable() {
- return flag.ErrHelp
+ return ErrSubCommandRequired
}
c.preRun()
@@ -857,6 +871,13 @@ func (c *Command) preRun() {
}
}
+// ExecuteContext is the same as Execute(), but sets the ctx on the command.
+// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle functions.
+func (c *Command) ExecuteContext(ctx context.Context) error {
+ c.ctx = ctx
+ return c.Execute()
+}
+
// Execute uses the args (os.Args[1:] by default)
// and run through the command tree finding appropriate matches
// for commands and then corresponding flags.
@@ -867,6 +888,10 @@ func (c *Command) Execute() error {
// ExecuteC executes the command.
func (c *Command) ExecuteC() (cmd *Command, err error) {
+ if c.ctx == nil {
+ c.ctx = context.Background()
+ }
+
// Regardless of what command execute is called on, run on Root only
if c.HasParent() {
return c.Root().ExecuteC()
@@ -911,6 +936,12 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
cmd.commandCalledAs.name = cmd.Name()
}
+ // We have to pass global context to children command
+ // if context is present on the parent command.
+ if cmd.ctx == nil {
+ cmd.ctx = c.ctx
+ }
+
err = cmd.execute(flags)
if err != nil {
// Always show help if requested, even if SilenceErrors is in
@@ -920,6 +951,14 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
return cmd, nil
}
+ // If command wasn't runnable, show full help, but do return the error.
+ // This will result in apps by default returning a non-success exit code, but also gives them the option to
+ // handle specially.
+ if err == ErrSubCommandRequired {
+ cmd.HelpFunc()(cmd, args)
+ return cmd, err
+ }
+
// If root command has SilentErrors flagged,
// all subcommands should respect it
if !cmd.SilenceErrors && !c.SilenceErrors {
@@ -1547,7 +1586,7 @@ func (c *Command) ParseFlags(args []string) error {
beforeErrorBufLen := c.flagErrorBuf.Len()
c.mergePersistentFlags()
- //do it here after merging all flags and just before parse
+ // do it here after merging all flags and just before parse
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
err := c.Flags().Parse(args)
diff --git a/vendor/github.com/spf13/cobra/go.mod b/vendor/github.com/spf13/cobra/go.mod
index 9a9eb65a3..dea1030ba 100644
--- a/vendor/github.com/spf13/cobra/go.mod
+++ b/vendor/github.com/spf13/cobra/go.mod
@@ -3,11 +3,10 @@ module github.com/spf13/cobra
go 1.12
require (
- github.com/BurntSushi/toml v0.3.1 // indirect
- github.com/cpuguy83/go-md2man v1.0.10
+ github.com/cpuguy83/go-md2man/v2 v2.0.0
github.com/inconshreveable/mousetrap v1.0.0
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/pflag v1.0.3
- github.com/spf13/viper v1.3.2
+ github.com/spf13/viper v1.4.0
gopkg.in/yaml.v2 v2.2.2
)
diff --git a/vendor/github.com/spf13/cobra/go.sum b/vendor/github.com/spf13/cobra/go.sum
index 9761f4d03..3aaa2ac0f 100644
--- a/vendor/github.com/spf13/cobra/go.sum
+++ b/vendor/github.com/spf13/cobra/go.sum
@@ -1,31 +1,91 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
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/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
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-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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 v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
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=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+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=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/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 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
@@ -34,18 +94,56 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+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=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
index e0364e9e7..bf89ecd21 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_format.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -32,7 +32,8 @@ func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args
return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
}
-// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -160,7 +161,8 @@ func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
return False(t, value, append([]interface{}{msg}, args...)...)
}
-// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -267,7 +269,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms
// InDeltaf asserts that the two numerals are within delta of each other.
//
-// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -325,14 +327,6 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
}
-// YAMLEqf asserts that two YAML strings are equivalent.
-func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
- if h, ok := t.(tHelper); ok {
- h.Helper()
- }
- return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
-}
-
// Lenf asserts that the specified object has specific length.
// Lenf also fails if the object has a type that len() not accept.
//
@@ -369,6 +363,17 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args .
return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
}
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
+}
+
// Nilf asserts that the specified object is nil.
//
// assert.Nilf(t, err, "error message %s", "formatted")
@@ -379,6 +384,15 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool
return Nil(t, object, append([]interface{}{msg}, args...)...)
}
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
// NoErrorf asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
@@ -392,6 +406,15 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
return NoError(t, err, append([]interface{}{msg}, args...)...)
}
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
@@ -462,6 +485,19 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
}
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
// NotSubsetf asserts that the specified list(array, slice...) contains not all
// elements given in the specified subset(array, slice...).
//
@@ -491,6 +527,18 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool
return Panics(t, f, append([]interface{}{msg}, args...)...)
}
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...)
+}
+
// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
@@ -557,6 +605,14 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
}
+// YAMLEqf asserts that two YAML strings are equivalent.
+func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
// Zerof asserts that i is the zero value for its type.
func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index 26830403a..75ecdcaa2 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -53,7 +53,8 @@ func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string,
return Containsf(a.t, s, contains, msg, args...)
}
-// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -61,7 +62,8 @@ func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
return DirExists(a.t, path, msgAndArgs...)
}
-// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -309,7 +311,8 @@ func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
return Falsef(a.t, value, msg, args...)
}
-// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -317,7 +320,8 @@ func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
return FileExists(a.t, path, msgAndArgs...)
}
-// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -521,7 +525,7 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}
// InDelta asserts that the two numerals are within delta of each other.
//
-// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+// a.InDelta(math.Pi, 22/7.0, 0.01)
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -563,7 +567,7 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del
// InDeltaf asserts that the two numerals are within delta of each other.
//
-// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -639,22 +643,6 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
return JSONEqf(a.t, expected, actual, msg, args...)
}
-// YAMLEq asserts that two YAML strings are equivalent.
-func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
- if h, ok := a.t.(tHelper); ok {
- h.Helper()
- }
- return YAMLEq(a.t, expected, actual, msgAndArgs...)
-}
-
-// YAMLEqf asserts that two YAML strings are equivalent.
-func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
- if h, ok := a.t.(tHelper); ok {
- h.Helper()
- }
- return YAMLEqf(a.t, expected, actual, msg, args...)
-}
-
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
@@ -727,6 +715,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
return Lessf(a.t, e1, e2, msg, args...)
}
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Never(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return Neverf(a.t, condition, waitFor, tick, msg, args...)
+}
+
// Nil asserts that the specified object is nil.
//
// a.Nil(err)
@@ -747,6 +757,24 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) b
return Nilf(a.t, object, msg, args...)
}
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExists(a.t, path, msgAndArgs...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoDirExistsf(a.t, path, msg, args...)
+}
+
// NoError asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
@@ -773,6 +801,24 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
return NoErrorf(a.t, err, msg, args...)
}
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExists(a.t, path, msgAndArgs...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NoFileExistsf(a.t, path, msg, args...)
+}
+
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
@@ -913,6 +959,32 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg
return NotRegexpf(a.t, rx, str, msg, args...)
}
+// NotSame asserts that two pointers do not reference the same object.
+//
+// a.NotSame(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSame(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// a.NotSamef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return NotSamef(a.t, expected, actual, msg, args...)
+}
+
// NotSubset asserts that the specified list(array, slice...) contains not all
// elements given in the specified subset(array, slice...).
//
@@ -961,6 +1033,30 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
return Panics(a.t, f, msgAndArgs...)
}
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithError("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithError(a.t, errString, f, msgAndArgs...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return PanicsWithErrorf(a.t, errString, f, msg, args...)
+}
+
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
@@ -1103,6 +1199,22 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
}
+// YAMLEq asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ return YAMLEqf(a.t, expected, actual, msg, args...)
+}
+
// Zero asserts that i is the zero value for its type.
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index 044da8b01..bdd81389a 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -11,6 +11,7 @@ import (
"reflect"
"regexp"
"runtime"
+ "runtime/debug"
"strings"
"time"
"unicode"
@@ -21,7 +22,7 @@ import (
yaml "gopkg.in/yaml.v2"
)
-//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl"
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
@@ -351,6 +352,19 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
}
+// validateEqualArgs checks whether provided arguments can be safely used in the
+// Equal/NotEqual functions.
+func validateEqualArgs(expected, actual interface{}) error {
+ if expected == nil && actual == nil {
+ return nil
+ }
+
+ if isFunction(expected) || isFunction(actual) {
+ return errors.New("cannot take func type as argument")
+ }
+ return nil
+}
+
// Same asserts that two pointers reference the same object.
//
// assert.Same(t, ptr1, ptr2)
@@ -362,18 +376,7 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
h.Helper()
}
- expectedPtr, actualPtr := reflect.ValueOf(expected), reflect.ValueOf(actual)
- if expectedPtr.Kind() != reflect.Ptr || actualPtr.Kind() != reflect.Ptr {
- return Fail(t, "Invalid operation: both arguments must be pointers", msgAndArgs...)
- }
-
- expectedType, actualType := reflect.TypeOf(expected), reflect.TypeOf(actual)
- if expectedType != actualType {
- return Fail(t, fmt.Sprintf("Pointer expected to be of type %v, but was %v",
- expectedType, actualType), msgAndArgs...)
- }
-
- if expected != actual {
+ if !samePointers(expected, actual) {
return Fail(t, fmt.Sprintf("Not same: \n"+
"expected: %p %#v\n"+
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
@@ -382,6 +385,42 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
return true
}
+// NotSame asserts that two pointers do not reference the same object.
+//
+// assert.NotSame(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ if samePointers(expected, actual) {
+ return Fail(t, fmt.Sprintf(
+ "Expected and actual point to the same object: %p %#v",
+ expected, expected), msgAndArgs...)
+ }
+ return true
+}
+
+// samePointers compares two generic interface objects and returns whether
+// they point to the same object
+func samePointers(first, second interface{}) bool {
+ firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
+ if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
+ return false
+ }
+
+ firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
+ if firstType != secondType {
+ return false
+ }
+
+ // compare pointer addresses
+ return first == second
+}
+
// formatUnequalValues takes two values of arbitrary types and returns string
// representations appropriate to be presented to the user.
//
@@ -393,9 +432,11 @@ func formatUnequalValues(expected, actual interface{}) (e string, a string) {
return fmt.Sprintf("%T(%#v)", expected, expected),
fmt.Sprintf("%T(%#v)", actual, actual)
}
-
- return fmt.Sprintf("%#v", expected),
- fmt.Sprintf("%#v", actual)
+ switch expected.(type) {
+ case time.Duration:
+ return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual)
+ }
+ return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual)
}
// EqualValues asserts that two objects are equal or convertable to the same types
@@ -901,15 +942,17 @@ func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
type PanicTestFunc func()
// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
-func didPanic(f PanicTestFunc) (bool, interface{}) {
+func didPanic(f PanicTestFunc) (bool, interface{}, string) {
didPanic := false
var message interface{}
+ var stack string
func() {
defer func() {
if message = recover(); message != nil {
didPanic = true
+ stack = string(debug.Stack())
}
}()
@@ -918,7 +961,7 @@ func didPanic(f PanicTestFunc) (bool, interface{}) {
}()
- return didPanic, message
+ return didPanic, message, stack
}
@@ -930,7 +973,7 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
h.Helper()
}
- if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
+ if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic {
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
}
@@ -946,12 +989,34 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr
h.Helper()
}
- funcDidPanic, panicValue := didPanic(f)
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
if !funcDidPanic {
return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
}
if panicValue != expected {
- return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...)
+ return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...)
+ }
+
+ return true
+}
+
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ funcDidPanic, panicValue, panickedStack := didPanic(f)
+ if !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
+ }
+ panicErr, ok := panicValue.(error)
+ if !ok || panicErr.Error() != errString {
+ return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...)
}
return true
@@ -965,8 +1030,8 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
h.Helper()
}
- if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
- return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...)
}
return true
@@ -1026,7 +1091,7 @@ func toFloat(x interface{}) (float64, bool) {
// InDelta asserts that the two numerals are within delta of each other.
//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1314,7 +1379,8 @@ func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
return true
}
-// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1332,7 +1398,24 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
return true
}
-// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ return true
+ }
+ if info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -1350,6 +1433,25 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
return true
}
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ info, err := os.Lstat(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return true
+ }
+ return true
+ }
+ if !info.IsDir() {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...)
+}
+
// JSONEq asserts that two JSON strings are equivalent.
//
// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
@@ -1439,15 +1541,6 @@ func diff(expected interface{}, actual interface{}) string {
return "\n\nDiff:\n" + diff
}
-// validateEqualArgs checks whether provided arguments can be safely used in the
-// Equal/NotEqual functions.
-func validateEqualArgs(expected, actual interface{}) error {
- if isFunction(expected) || isFunction(actual) {
- return errors.New("cannot take func type as argument")
- }
- return nil
-}
-
func isFunction(arg interface{}) bool {
if arg == nil {
return false
@@ -1475,24 +1568,59 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
h.Helper()
}
+ ch := make(chan bool, 1)
+
timer := time.NewTimer(waitFor)
- ticker := time.NewTicker(tick)
- checkPassed := make(chan bool)
defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
defer ticker.Stop()
- defer close(checkPassed)
- for {
+
+ for tick := ticker.C; ; {
select {
case <-timer.C:
return Fail(t, "Condition never satisfied", msgAndArgs...)
- case result := <-checkPassed:
- if result {
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
return true
}
- case <-ticker.C:
- go func() {
- checkPassed <- condition()
- }()
+ tick = ticker.C
+ }
+ }
+}
+
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+
+ ch := make(chan bool, 1)
+
+ timer := time.NewTimer(waitFor)
+ defer timer.Stop()
+
+ ticker := time.NewTicker(tick)
+ defer ticker.Stop()
+
+ for tick := ticker.C; ; {
+ select {
+ case <-timer.C:
+ return true
+ case <-tick:
+ tick = nil
+ go func() { ch <- condition() }()
+ case v := <-ch:
+ if v {
+ return Fail(t, "Condition satisfied", msgAndArgs...)
+ }
+ tick = ticker.C
}
}
}
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
index 9ad56851d..df189d234 100644
--- a/vendor/github.com/stretchr/testify/assert/forward_assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
@@ -13,4 +13,4 @@ func New(t TestingT) *Assertions {
}
}
-//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/stretchr/testify/require/forward_requirements.go b/vendor/github.com/stretchr/testify/require/forward_requirements.go
index ac71d4058..1dcb2338c 100644
--- a/vendor/github.com/stretchr/testify/require/forward_requirements.go
+++ b/vendor/github.com/stretchr/testify/require/forward_requirements.go
@@ -13,4 +13,4 @@ func New(t TestingT) *Assertions {
}
}
-//go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl -include-format-funcs
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
index c5903f5db..cf6c7b566 100644
--- a/vendor/github.com/stretchr/testify/require/require.go
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -66,7 +66,8 @@ func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args
t.FailNow()
}
-// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExists(t TestingT, path string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -77,7 +78,8 @@ func DirExists(t TestingT, path string, msgAndArgs ...interface{}) {
t.FailNow()
}
-// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func DirExistsf(t TestingT, path string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -275,12 +277,12 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) {
//
// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
- if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) {
- return
- }
if h, ok := t.(tHelper); ok {
h.Helper()
}
+ if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) {
+ return
+ }
t.FailNow()
}
@@ -289,12 +291,12 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t
//
// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
- if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) {
- return
- }
if h, ok := t.(tHelper); ok {
h.Helper()
}
+ if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) {
+ return
+ }
t.FailNow()
}
@@ -394,7 +396,8 @@ func Falsef(t TestingT, value bool, msg string, args ...interface{}) {
t.FailNow()
}
-// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func FileExists(t TestingT, path string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -405,7 +408,8 @@ func FileExists(t TestingT, path string, msgAndArgs ...interface{}) {
t.FailNow()
}
-// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func FileExistsf(t TestingT, path string, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -660,7 +664,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms
// InDelta asserts that the two numerals are within delta of each other.
//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+// assert.InDelta(t, math.Pi, 22/7.0, 0.01)
func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -717,7 +721,7 @@ func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta f
// InDeltaf asserts that the two numerals are within delta of each other.
//
-// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
if h, ok := t.(tHelper); ok {
h.Helper()
@@ -820,28 +824,6 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
t.FailNow()
}
-// YAMLEq asserts that two YAML strings are equivalent.
-func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
- if h, ok := t.(tHelper); ok {
- h.Helper()
- }
- if assert.YAMLEq(t, expected, actual, msgAndArgs...) {
- return
- }
- t.FailNow()
-}
-
-// YAMLEqf asserts that two YAML strings are equivalent.
-func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
- if h, ok := t.(tHelper); ok {
- h.Helper()
- }
- if assert.YAMLEqf(t, expected, actual, msg, args...) {
- return
- }
- t.FailNow()
-}
-
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
@@ -932,6 +914,34 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter
t.FailNow()
}
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond)
+func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Never(t, condition, waitFor, tick, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.Neverf(t, condition, waitFor, tick, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// Nil asserts that the specified object is nil.
//
// assert.Nil(t, err)
@@ -958,6 +968,30 @@ func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) {
t.FailNow()
}
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoDirExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoDirExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// NoError asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
@@ -990,6 +1024,30 @@ func NoErrorf(t TestingT, err error, msg string, args ...interface{}) {
t.FailNow()
}
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoFileExists(t, path, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NoFileExistsf(t, path, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
@@ -1166,6 +1224,38 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ..
t.FailNow()
}
+// NotSame asserts that two pointers do not reference the same object.
+//
+// assert.NotSame(t, ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSame(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.NotSamef(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// NotSubset asserts that the specified list(array, slice...) contains not all
// elements given in the specified subset(array, slice...).
//
@@ -1229,6 +1319,36 @@ func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
t.FailNow()
}
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() })
+func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithError(t, errString, f, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.PanicsWithErrorf(t, errString, f, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
@@ -1410,6 +1530,28 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
t.FailNow()
}
+// YAMLEq asserts that two YAML strings are equivalent.
+func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.YAMLEq(t, expected, actual, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.YAMLEqf(t, expected, actual, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// Zero asserts that i is the zero value for its type.
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
index 804fae035..5aac226df 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -54,7 +54,8 @@ func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string,
Containsf(a.t, s, contains, msg, args...)
}
-// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExists checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -62,7 +63,8 @@ func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) {
DirExists(a.t, path, msgAndArgs...)
}
-// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+// DirExistsf checks whether a directory exists in the given path. It also fails
+// if the path is a file rather a directory or there is an error checking whether it exists.
func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -310,7 +312,8 @@ func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) {
Falsef(a.t, value, msg, args...)
}
-// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExists checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -318,7 +321,8 @@ func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) {
FileExists(a.t, path, msgAndArgs...)
}
-// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+// FileExistsf checks whether a file exists in the given path. It also fails if
+// the path points to a directory or there is an error when trying to check the file.
func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -522,7 +526,7 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}
// InDelta asserts that the two numerals are within delta of each other.
//
-// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+// a.InDelta(math.Pi, 22/7.0, 0.01)
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -564,7 +568,7 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del
// InDeltaf asserts that the two numerals are within delta of each other.
//
-// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted")
func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) {
if h, ok := a.t.(tHelper); ok {
h.Helper()
@@ -640,22 +644,6 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
JSONEqf(a.t, expected, actual, msg, args...)
}
-// YAMLEq asserts that two YAML strings are equivalent.
-func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
- if h, ok := a.t.(tHelper); ok {
- h.Helper()
- }
- YAMLEq(a.t, expected, actual, msgAndArgs...)
-}
-
-// YAMLEqf asserts that two YAML strings are equivalent.
-func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) {
- if h, ok := a.t.(tHelper); ok {
- h.Helper()
- }
- YAMLEqf(a.t, expected, actual, msg, args...)
-}
-
// Len asserts that the specified object has specific length.
// Len also fails if the object has a type that len() not accept.
//
@@ -728,6 +716,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i
Lessf(a.t, e1, e2, msg, args...)
}
+// Never asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond)
+func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Never(a.t, condition, waitFor, tick, msgAndArgs...)
+}
+
+// Neverf asserts that the given condition doesn't satisfy in waitFor time,
+// periodically checking the target function each tick.
+//
+// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
+func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ Neverf(a.t, condition, waitFor, tick, msg, args...)
+}
+
// Nil asserts that the specified object is nil.
//
// a.Nil(err)
@@ -748,6 +758,24 @@ func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) {
Nilf(a.t, object, msg, args...)
}
+// NoDirExists checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoDirExists(a.t, path, msgAndArgs...)
+}
+
+// NoDirExistsf checks whether a directory does not exist in the given path.
+// It fails if the path points to an existing _directory_ only.
+func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoDirExistsf(a.t, path, msg, args...)
+}
+
// NoError asserts that a function returned no error (i.e. `nil`).
//
// actualObj, err := SomeFunction()
@@ -774,6 +802,24 @@ func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
NoErrorf(a.t, err, msg, args...)
}
+// NoFileExists checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoFileExists(a.t, path, msgAndArgs...)
+}
+
+// NoFileExistsf checks whether a file does not exist in a given path. It fails
+// if the path points to an existing _file_ only.
+func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NoFileExistsf(a.t, path, msg, args...)
+}
+
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
// specified substring or element.
//
@@ -914,6 +960,32 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg
NotRegexpf(a.t, rx, str, msg, args...)
}
+// NotSame asserts that two pointers do not reference the same object.
+//
+// a.NotSame(ptr1, ptr2)
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSame(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotSamef asserts that two pointers do not reference the same object.
+//
+// a.NotSamef(ptr1, ptr2, "error message %s", "formatted")
+//
+// Both arguments must be pointer variables. Pointer variable sameness is
+// determined based on the equality of both type and value.
+func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ NotSamef(a.t, expected, actual, msg, args...)
+}
+
// NotSubset asserts that the specified list(array, slice...) contains not all
// elements given in the specified subset(array, slice...).
//
@@ -962,6 +1034,30 @@ func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) {
Panics(a.t, f, msgAndArgs...)
}
+// PanicsWithError asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithError("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithError(a.t, errString, f, msgAndArgs...)
+}
+
+// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc
+// panics, and that the recovered panic value is an error that satisfies the
+// EqualError comparison.
+//
+// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ PanicsWithErrorf(a.t, errString, f, msg, args...)
+}
+
// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
// the recovered panic value equals the expected panic value.
//
@@ -1104,6 +1200,22 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
WithinDurationf(a.t, expected, actual, delta, msg, args...)
}
+// YAMLEq asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ YAMLEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// YAMLEqf asserts that two YAML strings are equivalent.
+func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ YAMLEqf(a.t, expected, actual, msg, args...)
+}
+
// Zero asserts that i is the zero value for its type.
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go
index 6b85c5ece..91772dfeb 100644
--- a/vendor/github.com/stretchr/testify/require/requirements.go
+++ b/vendor/github.com/stretchr/testify/require/requirements.go
@@ -26,4 +26,4 @@ type BoolAssertionFunc func(TestingT, bool, ...interface{})
// for table driven tests.
type ErrorAssertionFunc func(TestingT, error, ...interface{})
-//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs
+//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs"
diff --git a/vendor/github.com/uber/jaeger-lib/metrics/metrics.go b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go
index 0c6396888..0df0c662e 100644
--- a/vendor/github.com/uber/jaeger-lib/metrics/metrics.go
+++ b/vendor/github.com/uber/jaeger-lib/metrics/metrics.go
@@ -37,7 +37,7 @@ func MustInit(metrics interface{}, factory Factory, globalTags map[string]string
}
}
-// Init does the same as Init, but returns an error instead of
+// Init does the same as MustInit, but returns an error instead of
// panicking.
func Init(m interface{}, factory Factory, globalTags map[string]string) error {
// Allow user to opt out of reporting metrics by passing in nil.
diff --git a/vendor/github.com/xeipuuv/gojsonschema/.travis.yml b/vendor/github.com/xeipuuv/gojsonschema/.travis.yml
index 09ee789ca..36155164d 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/.travis.yml
+++ b/vendor/github.com/xeipuuv/gojsonschema/.travis.yml
@@ -1,11 +1,8 @@
language: go
go:
- - "1.5"
- - "1.6"
- - "1.7"
- - "1.8"
- - "1.9"
- "1.10"
+ - "1.11"
+ - "1.12"
before_install:
- go get github.com/xeipuuv/gojsonreference
- go get github.com/xeipuuv/gojsonpointer
diff --git a/vendor/github.com/xeipuuv/gojsonschema/README.md b/vendor/github.com/xeipuuv/gojsonschema/README.md
index 24ca34744..758f26df0 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/README.md
+++ b/vendor/github.com/xeipuuv/gojsonschema/README.md
@@ -1,5 +1,6 @@
[![GoDoc](https://godoc.org/github.com/xeipuuv/gojsonschema?status.svg)](https://godoc.org/github.com/xeipuuv/gojsonschema)
[![Build Status](https://travis-ci.org/xeipuuv/gojsonschema.svg)](https://travis-ci.org/xeipuuv/gojsonschema)
+[![Go Report Card](https://goreportcard.com/badge/github.com/xeipuuv/gojsonschema)](https://goreportcard.com/report/github.com/xeipuuv/gojsonschema)
# gojsonschema
@@ -343,7 +344,7 @@ Not all formats defined in draft-07 are available. Implemented formats are:
`email`, `uri` and `uri-reference` use the same validation code as their unicode counterparts `idn-email`, `iri` and `iri-reference`. If you rely on unicode support you should use the specific
unicode enabled formats for the sake of interoperability as other implementations might not support unicode in the regular formats.
-The validation code for `uri`, `idn-email` and their relatives use mostly standard library code. Go 1.5 and 1.6 contain some minor bugs with handling URIs and unicode. You are encouraged to use Go 1.7+ if you rely on these formats.
+The validation code for `uri`, `idn-email` and their relatives use mostly standard library code.
For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:
diff --git a/vendor/github.com/xeipuuv/gojsonschema/draft.go b/vendor/github.com/xeipuuv/gojsonschema/draft.go
index bfde4a2e1..7a0123cc7 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/draft.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/draft.go
@@ -22,8 +22,10 @@ import (
"github.com/xeipuuv/gojsonreference"
)
+// Draft is a JSON-schema draft version
type Draft int
+// Supported Draft versions
const (
Draft4 Draft = 4
Draft6 Draft = 6
@@ -42,17 +44,17 @@ var drafts draftConfigs
func init() {
drafts = []draftConfig{
- draftConfig{
+ {
Version: Draft4,
MetaSchemaURL: "http://json-schema.org/draft-04/schema",
MetaSchema: `{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}`,
},
- draftConfig{
+ {
Version: Draft6,
MetaSchemaURL: "http://json-schema.org/draft-06/schema",
MetaSchema: `{"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}`,
},
- draftConfig{
+ {
Version: Draft7,
MetaSchemaURL: "http://json-schema.org/draft-07/schema",
MetaSchema: `{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}`,
diff --git a/vendor/github.com/xeipuuv/gojsonschema/errors.go b/vendor/github.com/xeipuuv/gojsonschema/errors.go
index 2f01a1c2c..e4e9814f3 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/errors.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/errors.go
@@ -6,7 +6,7 @@ import (
"text/template"
)
-var errorTemplates errorTemplate = errorTemplate{template.New("errors-new"), sync.RWMutex{}}
+var errorTemplates = errorTemplate{template.New("errors-new"), sync.RWMutex{}}
// template.Template is not thread-safe for writing, so some locking is done
// sync.RWMutex is used for efficiently locking when new templates are created
@@ -16,157 +16,194 @@ type errorTemplate struct {
}
type (
- // RequiredError. ErrorDetails: property string
+
+ // FalseError. ErrorDetails: -
+ FalseError struct {
+ ResultErrorFields
+ }
+
+ // RequiredError indicates that a required field is missing
+ // ErrorDetails: property string
RequiredError struct {
ResultErrorFields
}
- // InvalidTypeError. ErrorDetails: expected, given
+ // InvalidTypeError indicates that a field has the incorrect type
+ // ErrorDetails: expected, given
InvalidTypeError struct {
ResultErrorFields
}
- // NumberAnyOfError. ErrorDetails: -
+ // NumberAnyOfError is produced in case of a failing "anyOf" validation
+ // ErrorDetails: -
NumberAnyOfError struct {
ResultErrorFields
}
- // NumberOneOfError. ErrorDetails: -
+ // NumberOneOfError is produced in case of a failing "oneOf" validation
+ // ErrorDetails: -
NumberOneOfError struct {
ResultErrorFields
}
- // NumberAllOfError. ErrorDetails: -
+ // NumberAllOfError is produced in case of a failing "allOf" validation
+ // ErrorDetails: -
NumberAllOfError struct {
ResultErrorFields
}
- // NumberNotError. ErrorDetails: -
+ // NumberNotError is produced if a "not" validation failed
+ // ErrorDetails: -
NumberNotError struct {
ResultErrorFields
}
- // MissingDependencyError. ErrorDetails: dependency
+ // MissingDependencyError is produced in case of a "missing dependency" problem
+ // ErrorDetails: dependency
MissingDependencyError struct {
ResultErrorFields
}
- // InternalError. ErrorDetails: error
+ // InternalError indicates an internal error
+ // ErrorDetails: error
InternalError struct {
ResultErrorFields
}
- // ConstError. ErrorDetails: allowed
+ // ConstError indicates a const error
+ // ErrorDetails: allowed
ConstError struct {
ResultErrorFields
}
- // EnumError. ErrorDetails: allowed
+ // EnumError indicates an enum error
+ // ErrorDetails: allowed
EnumError struct {
ResultErrorFields
}
- // ArrayNoAdditionalItemsError. ErrorDetails: -
+ // ArrayNoAdditionalItemsError is produced if additional items were found, but not allowed
+ // ErrorDetails: -
ArrayNoAdditionalItemsError struct {
ResultErrorFields
}
- // ArrayMinItemsError. ErrorDetails: min
+ // ArrayMinItemsError is produced if an array contains less items than the allowed minimum
+ // ErrorDetails: min
ArrayMinItemsError struct {
ResultErrorFields
}
- // ArrayMaxItemsError. ErrorDetails: max
+ // ArrayMaxItemsError is produced if an array contains more items than the allowed maximum
+ // ErrorDetails: max
ArrayMaxItemsError struct {
ResultErrorFields
}
- // ItemsMustBeUniqueError. ErrorDetails: type, i, j
+ // ItemsMustBeUniqueError is produced if an array requires unique items, but contains non-unique items
+ // ErrorDetails: type, i, j
ItemsMustBeUniqueError struct {
ResultErrorFields
}
- // ArrayContainsError. ErrorDetails:
+ // ArrayContainsError is produced if an array contains invalid items
+ // ErrorDetails:
ArrayContainsError struct {
ResultErrorFields
}
- // ArrayMinPropertiesError. ErrorDetails: min
+ // ArrayMinPropertiesError is produced if an object contains less properties than the allowed minimum
+ // ErrorDetails: min
ArrayMinPropertiesError struct {
ResultErrorFields
}
- // ArrayMaxPropertiesError. ErrorDetails: max
+ // ArrayMaxPropertiesError is produced if an object contains more properties than the allowed maximum
+ // ErrorDetails: max
ArrayMaxPropertiesError struct {
ResultErrorFields
}
- // AdditionalPropertyNotAllowedError. ErrorDetails: property
+ // AdditionalPropertyNotAllowedError is produced if an object has additional properties, but not allowed
+ // ErrorDetails: property
AdditionalPropertyNotAllowedError struct {
ResultErrorFields
}
- // InvalidPropertyPatternError. ErrorDetails: property, pattern
+ // InvalidPropertyPatternError is produced if an pattern was found
+ // ErrorDetails: property, pattern
InvalidPropertyPatternError struct {
ResultErrorFields
}
- // InvalidPopertyNameError. ErrorDetails: property
+ // InvalidPropertyNameError is produced if an invalid-named property was found
+ // ErrorDetails: property
InvalidPropertyNameError struct {
ResultErrorFields
}
- // StringLengthGTEError. ErrorDetails: min
+ // StringLengthGTEError is produced if a string is shorter than the minimum required length
+ // ErrorDetails: min
StringLengthGTEError struct {
ResultErrorFields
}
- // StringLengthLTEError. ErrorDetails: max
+ // StringLengthLTEError is produced if a string is longer than the maximum allowed length
+ // ErrorDetails: max
StringLengthLTEError struct {
ResultErrorFields
}
- // DoesNotMatchPatternError. ErrorDetails: pattern
+ // DoesNotMatchPatternError is produced if a string does not match the defined pattern
+ // ErrorDetails: pattern
DoesNotMatchPatternError struct {
ResultErrorFields
}
- // DoesNotMatchFormatError. ErrorDetails: format
+ // DoesNotMatchFormatError is produced if a string does not match the defined format
+ // ErrorDetails: format
DoesNotMatchFormatError struct {
ResultErrorFields
}
- // MultipleOfError. ErrorDetails: multiple
+ // MultipleOfError is produced if a number is not a multiple of the defined multipleOf
+ // ErrorDetails: multiple
MultipleOfError struct {
ResultErrorFields
}
- // NumberGTEError. ErrorDetails: min
+ // NumberGTEError is produced if a number is lower than the allowed minimum
+ // ErrorDetails: min
NumberGTEError struct {
ResultErrorFields
}
- // NumberGTError. ErrorDetails: min
+ // NumberGTError is produced if a number is lower than, or equal to the specified minimum, and exclusiveMinimum is set
+ // ErrorDetails: min
NumberGTError struct {
ResultErrorFields
}
- // NumberLTEError. ErrorDetails: max
+ // NumberLTEError is produced if a number is higher than the allowed maximum
+ // ErrorDetails: max
NumberLTEError struct {
ResultErrorFields
}
- // NumberLTError. ErrorDetails: max
+ // NumberLTError is produced if a number is higher than, or equal to the specified maximum, and exclusiveMaximum is set
+ // ErrorDetails: max
NumberLTError struct {
ResultErrorFields
}
- // ConditionThenError. ErrorDetails: -
+ // ConditionThenError is produced if a condition's "then" validation is invalid
+ // ErrorDetails: -
ConditionThenError struct {
ResultErrorFields
}
- // ConditionElseError. ErrorDetails: -
+ // ConditionElseError is produced if a condition's "else" condition is invalid
+ // ErrorDetails: -
ConditionElseError struct {
ResultErrorFields
}
@@ -177,6 +214,9 @@ func newError(err ResultError, context *JsonContext, value interface{}, locale l
var t string
var d string
switch err.(type) {
+ case *FalseError:
+ t = "false"
+ d = locale.False()
case *RequiredError:
t = "required"
d = locale.Required()
diff --git a/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go b/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
index 26217fca1..873ffc7d7 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
@@ -13,6 +13,7 @@ import (
type (
// FormatChecker is the interface all formatters added to FormatCheckerChain must implement
FormatChecker interface {
+ // IsFormat checks if input has the correct format and type
IsFormat(input interface{}) bool
}
@@ -21,13 +22,13 @@ type (
formatters map[string]FormatChecker
}
- // EmailFormatter verifies email address formats
+ // EmailFormatChecker verifies email address formats
EmailFormatChecker struct{}
- // IPV4FormatChecker verifies IP addresses in the ipv4 format
+ // IPV4FormatChecker verifies IP addresses in the IPv4 format
IPV4FormatChecker struct{}
- // IPV6FormatChecker verifies IP addresses in the ipv6 format
+ // IPV6FormatChecker verifies IP addresses in the IPv6 format
IPV6FormatChecker struct{}
// DateTimeFormatChecker verifies date/time formats per RFC3339 5.6
@@ -53,8 +54,29 @@ type (
// http://tools.ietf.org/html/rfc3339#section-5.6
DateTimeFormatChecker struct{}
+ // DateFormatChecker verifies date formats
+ //
+ // Valid format:
+ // Full Date: YYYY-MM-DD
+ //
+ // Where
+ // YYYY = 4DIGIT year
+ // MM = 2DIGIT month ; 01-12
+ // DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year
DateFormatChecker struct{}
+ // TimeFormatChecker verifies time formats
+ //
+ // Valid formats:
+ // Partial Time: HH:MM:SS
+ // Full Time: HH:MM:SSZ-07:00
+ //
+ // Where
+ // HH = 2DIGIT hour ; 00-23
+ // MM = 2DIGIT ; 00-59
+ // SS = 2DIGIT ; 00-58, 00-60 based on leap second rules
+ // T = Literal
+ // Z = Literal
TimeFormatChecker struct{}
// URIFormatChecker validates a URI with a valid Scheme per RFC3986
@@ -83,7 +105,7 @@ type (
)
var (
- // Formatters holds the valid formatters, and is a public variable
+ // FormatCheckers holds the valid formatters, and is a public variable
// so library users can add custom formatters
FormatCheckers = FormatCheckerChain{
formatters: map[string]FormatChecker{
@@ -119,7 +141,7 @@ var (
rxRelJSONPointer = regexp.MustCompile("^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)$")
- lock = new(sync.Mutex)
+ lock = new(sync.RWMutex)
)
// Add adds a FormatChecker to the FormatCheckerChain
@@ -143,9 +165,9 @@ func (c *FormatCheckerChain) Remove(name string) *FormatCheckerChain {
// Has checks to see if the FormatCheckerChain holds a FormatChecker with the given name
func (c *FormatCheckerChain) Has(name string) bool {
- lock.Lock()
+ lock.RLock()
_, ok := c.formatters[name]
- lock.Unlock()
+ lock.RUnlock()
return ok
}
@@ -153,55 +175,57 @@ func (c *FormatCheckerChain) Has(name string) bool {
// IsFormat will check an input against a FormatChecker with the given name
// to see if it is the correct format
func (c *FormatCheckerChain) IsFormat(name string, input interface{}) bool {
+ lock.RLock()
f, ok := c.formatters[name]
+ lock.RUnlock()
+ // If a format is unrecognized it should always pass validation
if !ok {
- return false
+ return true
}
return f.IsFormat(input)
}
+// IsFormat checks if input is a correctly formatted e-mail address
func (f EmailFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
_, err := mail.ParseAddress(asString)
-
return err == nil
}
-// Credit: https://github.com/asaskevich/govalidator
+// IsFormat checks if input is a correctly formatted IPv4-address
func (f IPV4FormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
+ // Credit: https://github.com/asaskevich/govalidator
ip := net.ParseIP(asString)
return ip != nil && strings.Contains(asString, ".")
}
-// Credit: https://github.com/asaskevich/govalidator
+// IsFormat checks if input is a correctly formatted IPv6=address
func (f IPV6FormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
+ // Credit: https://github.com/asaskevich/govalidator
ip := net.ParseIP(asString)
return ip != nil && strings.Contains(asString, ":")
}
+// IsFormat checks if input is a correctly formatted date/time per RFC3339 5.6
func (f DateTimeFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -222,18 +246,20 @@ func (f DateTimeFormatChecker) IsFormat(input interface{}) bool {
return false
}
+// IsFormat checks if input is a correctly formatted date (YYYY-MM-DD)
func (f DateFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
_, err := time.Parse("2006-01-02", asString)
return err == nil
}
+// IsFormat checks if input correctly formatted time (HH:MM:SS or HH:MM:SSZ-07:00)
func (f TimeFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -245,10 +271,10 @@ func (f TimeFormatChecker) IsFormat(input interface{}) bool {
return err == nil
}
+// IsFormat checks if input is correctly formatted URI with a valid Scheme per RFC3986
func (f URIFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -261,10 +287,10 @@ func (f URIFormatChecker) IsFormat(input interface{}) bool {
return !strings.Contains(asString, `\`)
}
+// IsFormat checks if input is a correctly formatted URI or relative-reference per RFC3986
func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -272,9 +298,10 @@ func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
return err == nil && !strings.Contains(asString, `\`)
}
+// IsFormat checks if input is a correctly formatted URI template per RFC6570
func (f URITemplateFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -286,31 +313,30 @@ func (f URITemplateFormatChecker) IsFormat(input interface{}) bool {
return rxURITemplate.MatchString(u.Path)
}
+// IsFormat checks if input is a correctly formatted hostname
func (f HostnameFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
return rxHostname.MatchString(asString) && len(asString) < 256
}
+// IsFormat checks if input is a correctly formatted UUID
func (f UUIDFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
return rxUUID.MatchString(asString)
}
-// IsFormat implements FormatChecker interface.
+// IsFormat checks if input is a correctly formatted regular expression
func (f RegexFormatChecker) IsFormat(input interface{}) bool {
-
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
@@ -318,24 +344,23 @@ func (f RegexFormatChecker) IsFormat(input interface{}) bool {
return true
}
_, err := regexp.Compile(asString)
- if err != nil {
- return false
- }
- return true
+ return err == nil
}
+// IsFormat checks if input is a correctly formatted JSON Pointer per RFC6901
func (f JSONPointerFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
return rxJSONPointer.MatchString(asString)
}
+// IsFormat checks if input is a correctly formatted relative JSON Pointer
func (f RelativeJSONPointerFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
- if ok == false {
+ if !ok {
return false
}
diff --git a/vendor/github.com/xeipuuv/gojsonschema/go.mod b/vendor/github.com/xeipuuv/gojsonschema/go.mod
new file mode 100644
index 000000000..b709d7fcd
--- /dev/null
+++ b/vendor/github.com/xeipuuv/gojsonschema/go.mod
@@ -0,0 +1,7 @@
+module github.com/xeipuuv/gojsonschema
+
+require (
+ github.com/stretchr/testify v1.3.0
+ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
+ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415
+)
diff --git a/vendor/github.com/xeipuuv/gojsonschema/go.sum b/vendor/github.com/xeipuuv/gojsonschema/go.sum
new file mode 100644
index 000000000..0e865ac75
--- /dev/null
+++ b/vendor/github.com/xeipuuv/gojsonschema/go.sum
@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+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/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
diff --git a/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go b/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go
index f40668a74..0e979707b 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/jsonContext.go
@@ -32,6 +32,7 @@ type JsonContext struct {
tail *JsonContext
}
+// NewJsonContext creates a new JsonContext
func NewJsonContext(head string, tail *JsonContext) *JsonContext {
return &JsonContext{head, tail}
}
diff --git a/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go b/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
index cfa5f6a3a..4f57ff789 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
@@ -43,8 +43,7 @@ import (
var osFS = osFileSystem(os.Open)
-// JSON loader interface
-
+// JSONLoader defines the JSON loader interface
type JSONLoader interface {
JsonSource() interface{}
LoadJSON() (interface{}, error)
@@ -52,17 +51,22 @@ type JSONLoader interface {
LoaderFactory() JSONLoaderFactory
}
+// JSONLoaderFactory defines the JSON loader factory interface
type JSONLoaderFactory interface {
+ // New creates a new JSON loader for the given source
New(source string) JSONLoader
}
+// DefaultJSONLoaderFactory is the default JSON loader factory
type DefaultJSONLoaderFactory struct {
}
+// FileSystemJSONLoaderFactory is a JSON loader factory that uses http.FileSystem
type FileSystemJSONLoaderFactory struct {
fs http.FileSystem
}
+// New creates a new JSON loader for the given source
func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
return &jsonReferenceLoader{
fs: osFS,
@@ -70,6 +74,7 @@ func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
}
}
+// New creates a new JSON loader for the given source
func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
return &jsonReferenceLoader{
fs: f.fs,
@@ -80,6 +85,7 @@ func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
// osFileSystem is a functional wrapper for os.Open that implements http.FileSystem.
type osFileSystem func(string) (*os.File, error)
+// Opens a file with the given name
func (o osFileSystem) Open(name string) (http.File, error) {
return o(name)
}
@@ -131,14 +137,14 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
return nil, err
}
- refToUrl := reference
- refToUrl.GetUrl().Fragment = ""
+ refToURL := reference
+ refToURL.GetUrl().Fragment = ""
var document interface{}
if reference.HasFileScheme {
- filename := strings.TrimPrefix(refToUrl.String(), "file://")
+ filename := strings.TrimPrefix(refToURL.String(), "file://")
if runtime.GOOS == "windows" {
// on Windows, a file URL may have an extra leading slash, use slashes
// instead of backslashes, and have spaces escaped
@@ -153,7 +159,7 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
} else {
- document, err = l.loadFromHTTP(refToUrl.String())
+ document, err = l.loadFromHTTP(refToURL.String())
if err != nil {
return nil, err
}
@@ -169,7 +175,7 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
// returned cached versions for metaschemas for drafts 4, 6 and 7
// for performance and allow for easier offline use
if metaSchema := drafts.GetMetaSchema(address); metaSchema != "" {
- return decodeJsonUsingNumber(strings.NewReader(metaSchema))
+ return decodeJSONUsingNumber(strings.NewReader(metaSchema))
}
resp, err := http.Get(address)
@@ -187,7 +193,7 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
return nil, err
}
- return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
+ return decodeJSONUsingNumber(bytes.NewReader(bodyBuff))
}
func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
@@ -202,7 +208,7 @@ func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
return nil, err
}
- return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
+ return decodeJSONUsingNumber(bytes.NewReader(bodyBuff))
}
@@ -224,13 +230,14 @@ func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
+// NewStringLoader creates a new JSONLoader, taking a string as source
func NewStringLoader(source string) JSONLoader {
return &jsonStringLoader{source: source}
}
func (l *jsonStringLoader) LoadJSON() (interface{}, error) {
- return decodeJsonUsingNumber(strings.NewReader(l.JsonSource().(string)))
+ return decodeJSONUsingNumber(strings.NewReader(l.JsonSource().(string)))
}
@@ -252,12 +259,13 @@ func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
+// NewBytesLoader creates a new JSONLoader, taking a `[]byte` as source
func NewBytesLoader(source []byte) JSONLoader {
return &jsonBytesLoader{source: source}
}
func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
- return decodeJsonUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
+ return decodeJSONUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
}
// JSON Go (types) loader
@@ -279,6 +287,7 @@ func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
+// NewGoLoader creates a new JSONLoader from a given Go struct
func NewGoLoader(source interface{}) JSONLoader {
return &jsonGoLoader{source: source}
}
@@ -292,7 +301,7 @@ func (l *jsonGoLoader) LoadJSON() (interface{}, error) {
return nil, err
}
- return decodeJsonUsingNumber(bytes.NewReader(jsonBytes))
+ return decodeJSONUsingNumber(bytes.NewReader(jsonBytes))
}
@@ -300,11 +309,13 @@ type jsonIOLoader struct {
buf *bytes.Buffer
}
+// NewReaderLoader creates a new JSON loader using the provided io.Reader
func NewReaderLoader(source io.Reader) (JSONLoader, io.Reader) {
buf := &bytes.Buffer{}
return &jsonIOLoader{buf: buf}, io.TeeReader(source, buf)
}
+// NewWriterLoader creates a new JSON loader using the provided io.Writer
func NewWriterLoader(source io.Writer) (JSONLoader, io.Writer) {
buf := &bytes.Buffer{}
return &jsonIOLoader{buf: buf}, io.MultiWriter(source, buf)
@@ -315,7 +326,7 @@ func (l *jsonIOLoader) JsonSource() interface{} {
}
func (l *jsonIOLoader) LoadJSON() (interface{}, error) {
- return decodeJsonUsingNumber(l.buf)
+ return decodeJSONUsingNumber(l.buf)
}
func (l *jsonIOLoader) JsonReference() (gojsonreference.JsonReference, error) {
@@ -334,7 +345,8 @@ type jsonRawLoader struct {
source interface{}
}
-func NewRawLoader(source interface{}) *jsonRawLoader {
+// NewRawLoader creates a new JSON raw loader for the given source
+func NewRawLoader(source interface{}) JSONLoader {
return &jsonRawLoader{source: source}
}
func (l *jsonRawLoader) JsonSource() interface{} {
@@ -350,7 +362,7 @@ func (l *jsonRawLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
-func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
+func decodeJSONUsingNumber(r io.Reader) (interface{}, error) {
var document interface{}
diff --git a/vendor/github.com/xeipuuv/gojsonschema/locales.go b/vendor/github.com/xeipuuv/gojsonschema/locales.go
index 9b4570f01..a416225cd 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/locales.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/locales.go
@@ -28,61 +28,163 @@ package gojsonschema
type (
// locale is an interface for defining custom error strings
locale interface {
+
+ // False returns a format-string for "false" schema validation errors
+ False() string
+
+ // Required returns a format-string for "required" schema validation errors
Required() string
+
+ // InvalidType returns a format-string for "invalid type" schema validation errors
InvalidType() string
+
+ // NumberAnyOf returns a format-string for "anyOf" schema validation errors
NumberAnyOf() string
+
+ // NumberOneOf returns a format-string for "oneOf" schema validation errors
NumberOneOf() string
+
+ // NumberAllOf returns a format-string for "allOf" schema validation errors
NumberAllOf() string
+
+ // NumberNot returns a format-string to format a NumberNotError
NumberNot() string
+
+ // MissingDependency returns a format-string for "missing dependency" schema validation errors
MissingDependency() string
+
+ // Internal returns a format-string for internal errors
Internal() string
+
+ // Const returns a format-string to format a ConstError
Const() string
+
+ // Enum returns a format-string to format an EnumError
Enum() string
+
+ // ArrayNotEnoughItems returns a format-string to format an error for arrays having not enough items to match positional list of schema
ArrayNotEnoughItems() string
+
+ // ArrayNoAdditionalItems returns a format-string to format an ArrayNoAdditionalItemsError
ArrayNoAdditionalItems() string
+
+ // ArrayMinItems returns a format-string to format an ArrayMinItemsError
ArrayMinItems() string
+
+ // ArrayMaxItems returns a format-string to format an ArrayMaxItemsError
ArrayMaxItems() string
+
+ // Unique returns a format-string to format an ItemsMustBeUniqueError
Unique() string
+
+ // ArrayContains returns a format-string to format an ArrayContainsError
ArrayContains() string
+
+ // ArrayMinProperties returns a format-string to format an ArrayMinPropertiesError
ArrayMinProperties() string
+
+ // ArrayMaxProperties returns a format-string to format an ArrayMaxPropertiesError
ArrayMaxProperties() string
+
+ // AdditionalPropertyNotAllowed returns a format-string to format an AdditionalPropertyNotAllowedError
AdditionalPropertyNotAllowed() string
+
+ // InvalidPropertyPattern returns a format-string to format an InvalidPropertyPatternError
InvalidPropertyPattern() string
+
+ // InvalidPropertyName returns a format-string to format an InvalidPropertyNameError
InvalidPropertyName() string
+
+ // StringGTE returns a format-string to format an StringLengthGTEError
StringGTE() string
+
+ // StringLTE returns a format-string to format an StringLengthLTEError
StringLTE() string
+
+ // DoesNotMatchPattern returns a format-string to format an DoesNotMatchPatternError
DoesNotMatchPattern() string
+
+ // DoesNotMatchFormat returns a format-string to format an DoesNotMatchFormatError
DoesNotMatchFormat() string
+
+ // MultipleOf returns a format-string to format an MultipleOfError
MultipleOf() string
+
+ // NumberGTE returns a format-string to format an NumberGTEError
NumberGTE() string
+
+ // NumberGT returns a format-string to format an NumberGTError
NumberGT() string
+
+ // NumberLTE returns a format-string to format an NumberLTEError
NumberLTE() string
+
+ // NumberLT returns a format-string to format an NumberLTError
NumberLT() string
// Schema validations
+
+ // RegexPattern returns a format-string to format a regex-pattern error
RegexPattern() string
+
+ // GreaterThanZero returns a format-string to format an error where a number must be greater than zero
GreaterThanZero() string
+
+ // MustBeOfA returns a format-string to format an error where a value is of the wrong type
MustBeOfA() string
+
+ // MustBeOfAn returns a format-string to format an error where a value is of the wrong type
MustBeOfAn() string
+
+ // CannotBeUsedWithout returns a format-string to format a "cannot be used without" error
CannotBeUsedWithout() string
+
+ // CannotBeGT returns a format-string to format an error where a value are greater than allowed
CannotBeGT() string
+
+ // MustBeOfType returns a format-string to format an error where a value does not match the required type
MustBeOfType() string
+
+ // MustBeValidRegex returns a format-string to format an error where a regex is invalid
MustBeValidRegex() string
+
+ // MustBeValidFormat returns a format-string to format an error where a value does not match the expected format
MustBeValidFormat() string
+
+ // MustBeGTEZero returns a format-string to format an error where a value must be greater or equal than 0
MustBeGTEZero() string
+
+ // KeyCannotBeGreaterThan returns a format-string to format an error where a key is greater than the maximum allowed
KeyCannotBeGreaterThan() string
+
+ // KeyItemsMustBeOfType returns a format-string to format an error where a key is of the wrong type
KeyItemsMustBeOfType() string
+
+ // KeyItemsMustBeUnique returns a format-string to format an error where keys are not unique
KeyItemsMustBeUnique() string
+
+ // ReferenceMustBeCanonical returns a format-string to format a "reference must be canonical" error
ReferenceMustBeCanonical() string
+
+ // NotAValidType returns a format-string to format an invalid type error
NotAValidType() string
+
+ // Duplicated returns a format-string to format an error where types are duplicated
Duplicated() string
+
+ // HttpBadStatus returns a format-string for errors when loading a schema using HTTP
HttpBadStatus() string
+
+ // ParseError returns a format-string for JSON parsing errors
ParseError() string
+ // ConditionThen returns a format-string for ConditionThenError errors
ConditionThen() string
+
+ // ConditionElse returns a format-string for ConditionElseError errors
ConditionElse() string
- // ErrorFormat
+ // ErrorFormat returns a format string for errors
ErrorFormat() string
}
@@ -90,214 +192,271 @@ type (
DefaultLocale struct{}
)
+// False returns a format-string for "false" schema validation errors
+func (l DefaultLocale) False() string {
+ return "False always fails validation"
+}
+
+// Required returns a format-string for "required" schema validation errors
func (l DefaultLocale) Required() string {
return `{{.property}} is required`
}
+// InvalidType returns a format-string for "invalid type" schema validation errors
func (l DefaultLocale) InvalidType() string {
return `Invalid type. Expected: {{.expected}}, given: {{.given}}`
}
+// NumberAnyOf returns a format-string for "anyOf" schema validation errors
func (l DefaultLocale) NumberAnyOf() string {
return `Must validate at least one schema (anyOf)`
}
+// NumberOneOf returns a format-string for "oneOf" schema validation errors
func (l DefaultLocale) NumberOneOf() string {
return `Must validate one and only one schema (oneOf)`
}
+// NumberAllOf returns a format-string for "allOf" schema validation errors
func (l DefaultLocale) NumberAllOf() string {
return `Must validate all the schemas (allOf)`
}
+// NumberNot returns a format-string to format a NumberNotError
func (l DefaultLocale) NumberNot() string {
return `Must not validate the schema (not)`
}
+// MissingDependency returns a format-string for "missing dependency" schema validation errors
func (l DefaultLocale) MissingDependency() string {
return `Has a dependency on {{.dependency}}`
}
+// Internal returns a format-string for internal errors
func (l DefaultLocale) Internal() string {
return `Internal Error {{.error}}`
}
+// Const returns a format-string to format a ConstError
func (l DefaultLocale) Const() string {
return `{{.field}} does not match: {{.allowed}}`
}
+// Enum returns a format-string to format an EnumError
func (l DefaultLocale) Enum() string {
return `{{.field}} must be one of the following: {{.allowed}}`
}
+// ArrayNoAdditionalItems returns a format-string to format an ArrayNoAdditionalItemsError
func (l DefaultLocale) ArrayNoAdditionalItems() string {
return `No additional items allowed on array`
}
+// ArrayNotEnoughItems returns a format-string to format an error for arrays having not enough items to match positional list of schema
func (l DefaultLocale) ArrayNotEnoughItems() string {
return `Not enough items on array to match positional list of schema`
}
+// ArrayMinItems returns a format-string to format an ArrayMinItemsError
func (l DefaultLocale) ArrayMinItems() string {
return `Array must have at least {{.min}} items`
}
+// ArrayMaxItems returns a format-string to format an ArrayMaxItemsError
func (l DefaultLocale) ArrayMaxItems() string {
return `Array must have at most {{.max}} items`
}
+// Unique returns a format-string to format an ItemsMustBeUniqueError
func (l DefaultLocale) Unique() string {
return `{{.type}} items[{{.i}},{{.j}}] must be unique`
}
+// ArrayContains returns a format-string to format an ArrayContainsError
func (l DefaultLocale) ArrayContains() string {
return `At least one of the items must match`
}
+// ArrayMinProperties returns a format-string to format an ArrayMinPropertiesError
func (l DefaultLocale) ArrayMinProperties() string {
return `Must have at least {{.min}} properties`
}
+// ArrayMaxProperties returns a format-string to format an ArrayMaxPropertiesError
func (l DefaultLocale) ArrayMaxProperties() string {
return `Must have at most {{.max}} properties`
}
+// AdditionalPropertyNotAllowed returns a format-string to format an AdditionalPropertyNotAllowedError
func (l DefaultLocale) AdditionalPropertyNotAllowed() string {
return `Additional property {{.property}} is not allowed`
}
+// InvalidPropertyPattern returns a format-string to format an InvalidPropertyPatternError
func (l DefaultLocale) InvalidPropertyPattern() string {
return `Property "{{.property}}" does not match pattern {{.pattern}}`
}
+// InvalidPropertyName returns a format-string to format an InvalidPropertyNameError
func (l DefaultLocale) InvalidPropertyName() string {
return `Property name of "{{.property}}" does not match`
}
+// StringGTE returns a format-string to format an StringLengthGTEError
func (l DefaultLocale) StringGTE() string {
return `String length must be greater than or equal to {{.min}}`
}
+// StringLTE returns a format-string to format an StringLengthLTEError
func (l DefaultLocale) StringLTE() string {
return `String length must be less than or equal to {{.max}}`
}
+// DoesNotMatchPattern returns a format-string to format an DoesNotMatchPatternError
func (l DefaultLocale) DoesNotMatchPattern() string {
return `Does not match pattern '{{.pattern}}'`
}
+// DoesNotMatchFormat returns a format-string to format an DoesNotMatchFormatError
func (l DefaultLocale) DoesNotMatchFormat() string {
return `Does not match format '{{.format}}'`
}
+// MultipleOf returns a format-string to format an MultipleOfError
func (l DefaultLocale) MultipleOf() string {
return `Must be a multiple of {{.multiple}}`
}
+// NumberGTE returns the format string to format a NumberGTEError
func (l DefaultLocale) NumberGTE() string {
return `Must be greater than or equal to {{.min}}`
}
+// NumberGT returns the format string to format a NumberGTError
func (l DefaultLocale) NumberGT() string {
return `Must be greater than {{.min}}`
}
+// NumberLTE returns the format string to format a NumberLTEError
func (l DefaultLocale) NumberLTE() string {
return `Must be less than or equal to {{.max}}`
}
+// NumberLT returns the format string to format a NumberLTError
func (l DefaultLocale) NumberLT() string {
return `Must be less than {{.max}}`
}
// Schema validators
+
+// RegexPattern returns a format-string to format a regex-pattern error
func (l DefaultLocale) RegexPattern() string {
return `Invalid regex pattern '{{.pattern}}'`
}
+// GreaterThanZero returns a format-string to format an error where a number must be greater than zero
func (l DefaultLocale) GreaterThanZero() string {
return `{{.number}} must be strictly greater than 0`
}
+// MustBeOfA returns a format-string to format an error where a value is of the wrong type
func (l DefaultLocale) MustBeOfA() string {
return `{{.x}} must be of a {{.y}}`
}
+// MustBeOfAn returns a format-string to format an error where a value is of the wrong type
func (l DefaultLocale) MustBeOfAn() string {
return `{{.x}} must be of an {{.y}}`
}
+// CannotBeUsedWithout returns a format-string to format a "cannot be used without" error
func (l DefaultLocale) CannotBeUsedWithout() string {
return `{{.x}} cannot be used without {{.y}}`
}
+// CannotBeGT returns a format-string to format an error where a value are greater than allowed
func (l DefaultLocale) CannotBeGT() string {
return `{{.x}} cannot be greater than {{.y}}`
}
+// MustBeOfType returns a format-string to format an error where a value does not match the required type
func (l DefaultLocale) MustBeOfType() string {
return `{{.key}} must be of type {{.type}}`
}
+// MustBeValidRegex returns a format-string to format an error where a regex is invalid
func (l DefaultLocale) MustBeValidRegex() string {
return `{{.key}} must be a valid regex`
}
+// MustBeValidFormat returns a format-string to format an error where a value does not match the expected format
func (l DefaultLocale) MustBeValidFormat() string {
return `{{.key}} must be a valid format {{.given}}`
}
+// MustBeGTEZero returns a format-string to format an error where a value must be greater or equal than 0
func (l DefaultLocale) MustBeGTEZero() string {
return `{{.key}} must be greater than or equal to 0`
}
+// KeyCannotBeGreaterThan returns a format-string to format an error where a value is greater than the maximum allowed
func (l DefaultLocale) KeyCannotBeGreaterThan() string {
return `{{.key}} cannot be greater than {{.y}}`
}
+// KeyItemsMustBeOfType returns a format-string to format an error where a key is of the wrong type
func (l DefaultLocale) KeyItemsMustBeOfType() string {
return `{{.key}} items must be {{.type}}`
}
+// KeyItemsMustBeUnique returns a format-string to format an error where keys are not unique
func (l DefaultLocale) KeyItemsMustBeUnique() string {
return `{{.key}} items must be unique`
}
+// ReferenceMustBeCanonical returns a format-string to format a "reference must be canonical" error
func (l DefaultLocale) ReferenceMustBeCanonical() string {
return `Reference {{.reference}} must be canonical`
}
+// NotAValidType returns a format-string to format an invalid type error
func (l DefaultLocale) NotAValidType() string {
return `has a primitive type that is NOT VALID -- given: {{.given}} Expected valid values are:{{.expected}}`
}
+// Duplicated returns a format-string to format an error where types are duplicated
func (l DefaultLocale) Duplicated() string {
return `{{.type}} type is duplicated`
}
+// HttpBadStatus returns a format-string for errors when loading a schema using HTTP
func (l DefaultLocale) HttpBadStatus() string {
return `Could not read schema from HTTP, response status is {{.status}}`
}
+// ErrorFormat returns a format string for errors
// Replacement options: field, description, context, value
func (l DefaultLocale) ErrorFormat() string {
return `{{.field}}: {{.description}}`
}
-//Parse error
+// ParseError returns a format-string for JSON parsing errors
func (l DefaultLocale) ParseError() string {
return `Expected: {{.expected}}, given: Invalid JSON`
}
-//If/Else
+// ConditionThen returns a format-string for ConditionThenError errors
+// If/Else
func (l DefaultLocale) ConditionThen() string {
return `Must validate "then" as "if" was valid`
}
+// ConditionElse returns a format-string for ConditionElseError errors
func (l DefaultLocale) ConditionElse() string {
return `Must validate "else" as "if" was not valid`
}
+// constants
const (
STRING_NUMBER = "number"
STRING_ARRAY_OF_STRINGS = "array of strings"
diff --git a/vendor/github.com/xeipuuv/gojsonschema/result.go b/vendor/github.com/xeipuuv/gojsonschema/result.go
index 040d35c8d..0a0179148 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/result.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/result.go
@@ -37,19 +37,34 @@ type (
// ResultError is the interface that library errors must implement
ResultError interface {
+ // Field returns the field name without the root context
+ // i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName
Field() string
+ // SetType sets the error-type
SetType(string)
+ // Type returns the error-type
Type() string
+ // SetContext sets the JSON-context for the error
SetContext(*JsonContext)
+ // Context returns the JSON-context of the error
Context() *JsonContext
+ // SetDescription sets a description for the error
SetDescription(string)
+ // Description returns the description of the error
Description() string
+ // SetDescriptionFormat sets the format for the description in the default text/template format
SetDescriptionFormat(string)
+ // DescriptionFormat returns the format for the description in the default text/template format
DescriptionFormat() string
+ // SetValue sets the value related to the error
SetValue(interface{})
+ // Value returns the value related to the error
Value() interface{}
+ // SetDetails sets the details specific to the error
SetDetails(ErrorDetails)
+ // Details returns details about the error
Details() ErrorDetails
+ // String returns a string representation of the error
String() string
}
@@ -65,6 +80,7 @@ type (
details ErrorDetails
}
+ // Result holds the result of a validation
Result struct {
errors []ResultError
// Scores how well the validation matched. Useful in generating
@@ -73,60 +89,73 @@ type (
}
)
-// Field outputs the field name without the root context
+// Field returns the field name without the root context
// i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName
func (v *ResultErrorFields) Field() string {
return strings.TrimPrefix(v.context.String(), STRING_ROOT_SCHEMA_PROPERTY+".")
}
+// SetType sets the error-type
func (v *ResultErrorFields) SetType(errorType string) {
v.errorType = errorType
}
+// Type returns the error-type
func (v *ResultErrorFields) Type() string {
return v.errorType
}
+// SetContext sets the JSON-context for the error
func (v *ResultErrorFields) SetContext(context *JsonContext) {
v.context = context
}
+// Context returns the JSON-context of the error
func (v *ResultErrorFields) Context() *JsonContext {
return v.context
}
+// SetDescription sets a description for the error
func (v *ResultErrorFields) SetDescription(description string) {
v.description = description
}
+// Description returns the description of the error
func (v *ResultErrorFields) Description() string {
return v.description
}
+// SetDescriptionFormat sets the format for the description in the default text/template format
func (v *ResultErrorFields) SetDescriptionFormat(descriptionFormat string) {
v.descriptionFormat = descriptionFormat
}
+// DescriptionFormat returns the format for the description in the default text/template format
func (v *ResultErrorFields) DescriptionFormat() string {
return v.descriptionFormat
}
+// SetValue sets the value related to the error
func (v *ResultErrorFields) SetValue(value interface{}) {
v.value = value
}
+// Value returns the value related to the error
func (v *ResultErrorFields) Value() interface{} {
return v.value
}
+// SetDetails sets the details specific to the error
func (v *ResultErrorFields) SetDetails(details ErrorDetails) {
v.details = details
}
+// Details returns details about the error
func (v *ResultErrorFields) Details() ErrorDetails {
return v.details
}
+// String returns a string representation of the error
func (v ResultErrorFields) String() string {
// as a fallback, the value is displayed go style
valueString := fmt.Sprintf("%v", v.value)
@@ -135,7 +164,7 @@ func (v ResultErrorFields) String() string {
if v.value == nil {
valueString = TYPE_NULL
} else {
- if vs, err := marshalToJsonString(v.value); err == nil {
+ if vs, err := marshalToJSONString(v.value); err == nil {
if vs == nil {
valueString = TYPE_NULL
} else {
@@ -152,15 +181,17 @@ func (v ResultErrorFields) String() string {
})
}
+// Valid indicates if no errors were found
func (v *Result) Valid() bool {
return len(v.errors) == 0
}
+// Errors returns the errors that were found
func (v *Result) Errors() []ResultError {
return v.errors
}
-// Add a fully filled error to the error set
+// AddError appends a fully filled error to the error set
// SetDescription() will be called with the result of the parsed err.DescriptionFormat()
func (v *Result) AddError(err ResultError, details ErrorDetails) {
if _, exists := details["context"]; !exists && err.Context() != nil {
diff --git a/vendor/github.com/xeipuuv/gojsonschema/schema.go b/vendor/github.com/xeipuuv/gojsonschema/schema.go
index 323fe8559..9e93cd795 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/schema.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/schema.go
@@ -45,10 +45,12 @@ var (
ErrorTemplateFuncs template.FuncMap
)
+// NewSchema instances a schema using the given JSONLoader
func NewSchema(l JSONLoader) (*Schema, error) {
return NewSchemaLoader().Compile(l)
}
+// Schema holds a schema
type Schema struct {
documentReference gojsonreference.JsonReference
rootSchema *subSchema
@@ -61,6 +63,7 @@ func (d *Schema) parse(document interface{}, draft Draft) error {
return d.parseSchema(document, d.rootSchema)
}
+// SetRootSchemaName sets the root-schema name
func (d *Schema) SetRootSchemaName(name string) {
d.rootSchema.property = name
}
@@ -83,11 +86,8 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
// As of draft 6 "true" is equivalent to an empty schema "{}" and false equals "{"not":{}}"
if *currentSchema.draft >= Draft6 && isKind(documentNode, reflect.Bool) {
b := documentNode.(bool)
- if b {
- documentNode = map[string]interface{}{}
- } else {
- documentNode = map[string]interface{}{"not": true}
- }
+ currentSchema.pass = &b
+ return nil
}
if !isKind(documentNode, reflect.Map) {
@@ -267,8 +267,9 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
"given": KEY_TYPE,
},
))
- } else {
- currentSchema.types.Add(typeInArray.(string))
+ }
+ if err := currentSchema.types.Add(typeInArray.(string)); err != nil {
+ return err
}
}
@@ -382,7 +383,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if isKind(itemElement, reflect.Map, reflect.Bool) {
newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS}
newSchema.ref = currentSchema.ref
- currentSchema.AddItemsChild(newSchema)
+ currentSchema.itemsChildren = append(currentSchema.itemsChildren, newSchema)
err := d.parseSchema(itemElement, newSchema)
if err != nil {
return err
@@ -401,7 +402,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
} else if isKind(m[KEY_ITEMS], reflect.Map, reflect.Bool) {
newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS}
newSchema.ref = currentSchema.ref
- currentSchema.AddItemsChild(newSchema)
+ currentSchema.itemsChildren = append(currentSchema.itemsChildren, newSchema)
err := d.parseSchema(m[KEY_ITEMS], newSchema)
if err != nil {
return err
@@ -507,7 +508,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
currentSchema.exclusiveMinimum = currentSchema.minimum
currentSchema.minimum = nil
}
- } else if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
+ } else if isJSONNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
currentSchema.exclusiveMinimum = mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM])
} else {
return errors.New(formatErrorDescription(
@@ -519,7 +520,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
))
}
default:
- if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
+ if isJSONNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
currentSchema.exclusiveMinimum = mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM])
} else {
return errors.New(formatErrorDescription(
@@ -578,7 +579,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
currentSchema.exclusiveMaximum = currentSchema.maximum
currentSchema.maximum = nil
}
- } else if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
+ } else if isJSONNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
currentSchema.exclusiveMaximum = mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM])
} else {
return errors.New(formatErrorDescription(
@@ -590,7 +591,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
))
}
default:
- if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
+ if isJSONNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
currentSchema.exclusiveMaximum = mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM])
} else {
return errors.New(formatErrorDescription(
@@ -669,9 +670,13 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if existsMapKey(m, KEY_FORMAT) {
formatString, ok := m[KEY_FORMAT].(string)
- if ok && FormatCheckers.Has(formatString) {
- currentSchema.format = formatString
+ if !ok {
+ return errors.New(formatErrorDescription(
+ Locale.MustBeOfType(),
+ ErrorDetails{"key": KEY_FORMAT, "type": TYPE_STRING},
+ ))
}
+ currentSchema.format = formatString
}
// validation : object
@@ -724,10 +729,13 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
requiredValues := m[KEY_REQUIRED].([]interface{})
for _, requiredValue := range requiredValues {
if isKind(requiredValue, reflect.String) {
- err := currentSchema.AddRequired(requiredValue.(string))
- if err != nil {
- return err
+ if isStringInSlice(currentSchema.required, requiredValue.(string)) {
+ return errors.New(formatErrorDescription(
+ Locale.KeyItemsMustBeUnique(),
+ ErrorDetails{"key": KEY_REQUIRED},
+ ))
}
+ currentSchema.required = append(currentSchema.required, requiredValue.(string))
} else {
return errors.New(formatErrorDescription(
Locale.KeyItemsMustBeOfType(),
@@ -802,19 +810,27 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
// validation : all
if existsMapKey(m, KEY_CONST) && *currentSchema.draft >= Draft6 {
- err := currentSchema.AddConst(m[KEY_CONST])
+ is, err := marshalWithoutNumber(m[KEY_CONST])
if err != nil {
return err
}
+ currentSchema._const = is
}
if existsMapKey(m, KEY_ENUM) {
if isKind(m[KEY_ENUM], reflect.Slice) {
for _, v := range m[KEY_ENUM].([]interface{}) {
- err := currentSchema.AddEnum(v)
+ is, err := marshalWithoutNumber(v)
if err != nil {
return err
}
+ if isStringInSlice(currentSchema.enum, *is) {
+ return errors.New(formatErrorDescription(
+ Locale.KeyItemsMustBeUnique(),
+ ErrorDetails{"key": KEY_ENUM},
+ ))
+ }
+ currentSchema.enum = append(currentSchema.enum, *is)
}
} else {
return errors.New(formatErrorDescription(
@@ -830,7 +846,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if isKind(m[KEY_ONE_OF], reflect.Slice) {
for _, v := range m[KEY_ONE_OF].([]interface{}) {
newSchema := &subSchema{property: KEY_ONE_OF, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.AddOneOf(newSchema)
+ currentSchema.oneOf = append(currentSchema.oneOf, newSchema)
err := d.parseSchema(v, newSchema)
if err != nil {
return err
@@ -848,7 +864,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if isKind(m[KEY_ANY_OF], reflect.Slice) {
for _, v := range m[KEY_ANY_OF].([]interface{}) {
newSchema := &subSchema{property: KEY_ANY_OF, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.AddAnyOf(newSchema)
+ currentSchema.anyOf = append(currentSchema.anyOf, newSchema)
err := d.parseSchema(v, newSchema)
if err != nil {
return err
@@ -866,7 +882,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if isKind(m[KEY_ALL_OF], reflect.Slice) {
for _, v := range m[KEY_ALL_OF].([]interface{}) {
newSchema := &subSchema{property: KEY_ALL_OF, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.AddAllOf(newSchema)
+ currentSchema.allOf = append(currentSchema.allOf, newSchema)
err := d.parseSchema(v, newSchema)
if err != nil {
return err
@@ -883,7 +899,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if existsMapKey(m, KEY_NOT) {
if isKind(m[KEY_NOT], reflect.Map, reflect.Bool) {
newSchema := &subSchema{property: KEY_NOT, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.SetNot(newSchema)
+ currentSchema.not = newSchema
err := d.parseSchema(m[KEY_NOT], newSchema)
if err != nil {
return err
@@ -900,7 +916,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if existsMapKey(m, KEY_IF) {
if isKind(m[KEY_IF], reflect.Map, reflect.Bool) {
newSchema := &subSchema{property: KEY_IF, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.SetIf(newSchema)
+ currentSchema._if = newSchema
err := d.parseSchema(m[KEY_IF], newSchema)
if err != nil {
return err
@@ -916,7 +932,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if existsMapKey(m, KEY_THEN) {
if isKind(m[KEY_THEN], reflect.Map, reflect.Bool) {
newSchema := &subSchema{property: KEY_THEN, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.SetThen(newSchema)
+ currentSchema._then = newSchema
err := d.parseSchema(m[KEY_THEN], newSchema)
if err != nil {
return err
@@ -932,7 +948,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
if existsMapKey(m, KEY_ELSE) {
if isKind(m[KEY_ELSE], reflect.Map, reflect.Bool) {
newSchema := &subSchema{property: KEY_ELSE, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.SetElse(newSchema)
+ currentSchema._else = newSchema
err := d.parseSchema(m[KEY_ELSE], newSchema)
if err != nil {
return err
@@ -1004,7 +1020,7 @@ func (d *Schema) parseProperties(documentNode interface{}, currentSchema *subSch
for k := range m {
schemaProperty := k
newSchema := &subSchema{property: schemaProperty, parent: currentSchema, ref: currentSchema.ref}
- currentSchema.AddPropertiesChild(newSchema)
+ currentSchema.propertiesChildren = append(currentSchema.propertiesChildren, newSchema)
err := d.parseSchema(m[k], newSchema)
if err != nil {
return err
@@ -1042,9 +1058,8 @@ func (d *Schema) parseDependencies(documentNode interface{}, currentSchema *subS
"type": STRING_SCHEMA_OR_ARRAY_OF_STRINGS,
},
))
- } else {
- valuesToRegister = append(valuesToRegister, value.(string))
}
+ valuesToRegister = append(valuesToRegister, value.(string))
currentSchema.dependencies[k] = valuesToRegister
}
diff --git a/vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go b/vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go
index 95e0568ab..20db0c1f9 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go
@@ -21,6 +21,7 @@ import (
"github.com/xeipuuv/gojsonreference"
)
+// SchemaLoader is used to load schemas
type SchemaLoader struct {
pool *schemaPool
AutoDetect bool
@@ -28,6 +29,7 @@ type SchemaLoader struct {
Draft Draft
}
+// NewSchemaLoader creates a new NewSchemaLoader
func NewSchemaLoader() *SchemaLoader {
ps := &SchemaLoader{
@@ -141,6 +143,7 @@ func (sl *SchemaLoader) AddSchema(url string, loader JSONLoader) error {
return sl.pool.parseReferences(doc, ref, true)
}
+// Compile loads and compiles a schema
func (sl *SchemaLoader) Compile(rootSchema JSONLoader) (*Schema, error) {
ref, err := rootSchema.JsonReference()
diff --git a/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go b/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
index f124e038d..35b1cc630 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
@@ -150,12 +150,12 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche
}
// Create a deep copy, so we can remove the fragment part later on without altering the original
- refToUrl, _ := gojsonreference.NewJsonReference(reference.String())
+ refToURL, _ := gojsonreference.NewJsonReference(reference.String())
// First check if the given fragment is a location independent identifier
// http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3
- if spd, ok = p.schemaPoolDocuments[refToUrl.String()]; ok {
+ if spd, ok = p.schemaPoolDocuments[refToURL.String()]; ok {
if internalLogEnabled {
internalLog(" From pool")
}
@@ -165,9 +165,9 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche
// If the given reference is not a location independent identifier,
// strip the fragment and look for a document with it's base URI
- refToUrl.GetUrl().Fragment = ""
+ refToURL.GetUrl().Fragment = ""
- if cachedSpd, ok := p.schemaPoolDocuments[refToUrl.String()]; ok {
+ if cachedSpd, ok := p.schemaPoolDocuments[refToURL.String()]; ok {
document, _, err := reference.GetPointer().Get(cachedSpd.Document)
if err != nil {
@@ -200,7 +200,7 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche
}
// add the whole document to the pool for potential re-use
- p.parseReferences(document, refToUrl, true)
+ p.parseReferences(document, refToURL, true)
_, draft, _ = parseSchemaURL(document)
diff --git a/vendor/github.com/xeipuuv/gojsonschema/subSchema.go b/vendor/github.com/xeipuuv/gojsonschema/subSchema.go
index 362d86ca9..ec779812c 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/subSchema.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/subSchema.go
@@ -27,14 +27,12 @@
package gojsonschema
import (
- "errors"
+ "github.com/xeipuuv/gojsonreference"
"math/big"
"regexp"
- "strings"
-
- "github.com/xeipuuv/gojsonreference"
)
+// Constants
const (
KEY_SCHEMA = "$schema"
KEY_ID = "id"
@@ -88,6 +86,9 @@ type subSchema struct {
property string
+ // Quick pass/fail for boolean schemas
+ pass *bool
+
// Types associated with the subSchema
types jsonSchemaType
@@ -146,111 +147,3 @@ type subSchema struct {
_then *subSchema
_else *subSchema
}
-
-func (s *subSchema) AddConst(i interface{}) error {
-
- is, err := marshalWithoutNumber(i)
- if err != nil {
- return err
- }
- s._const = is
- return nil
-}
-
-func (s *subSchema) AddEnum(i interface{}) error {
-
- is, err := marshalWithoutNumber(i)
- if err != nil {
- return err
- }
-
- if isStringInSlice(s.enum, *is) {
- return errors.New(formatErrorDescription(
- Locale.KeyItemsMustBeUnique(),
- ErrorDetails{"key": KEY_ENUM},
- ))
- }
-
- s.enum = append(s.enum, *is)
-
- return nil
-}
-
-func (s *subSchema) ContainsEnum(i interface{}) (bool, error) {
-
- is, err := marshalWithoutNumber(i)
- if err != nil {
- return false, err
- }
-
- return isStringInSlice(s.enum, *is), nil
-}
-
-func (s *subSchema) AddOneOf(subSchema *subSchema) {
- s.oneOf = append(s.oneOf, subSchema)
-}
-
-func (s *subSchema) AddAllOf(subSchema *subSchema) {
- s.allOf = append(s.allOf, subSchema)
-}
-
-func (s *subSchema) AddAnyOf(subSchema *subSchema) {
- s.anyOf = append(s.anyOf, subSchema)
-}
-
-func (s *subSchema) SetNot(subSchema *subSchema) {
- s.not = subSchema
-}
-
-func (s *subSchema) SetIf(subSchema *subSchema) {
- s._if = subSchema
-}
-
-func (s *subSchema) SetThen(subSchema *subSchema) {
- s._then = subSchema
-}
-
-func (s *subSchema) SetElse(subSchema *subSchema) {
- s._else = subSchema
-}
-
-func (s *subSchema) AddRequired(value string) error {
-
- if isStringInSlice(s.required, value) {
- return errors.New(formatErrorDescription(
- Locale.KeyItemsMustBeUnique(),
- ErrorDetails{"key": KEY_REQUIRED},
- ))
- }
-
- s.required = append(s.required, value)
-
- return nil
-}
-
-func (s *subSchema) AddItemsChild(child *subSchema) {
- s.itemsChildren = append(s.itemsChildren, child)
-}
-
-func (s *subSchema) AddPropertiesChild(child *subSchema) {
- s.propertiesChildren = append(s.propertiesChildren, child)
-}
-
-func (s *subSchema) PatternPropertiesString() string {
-
- if s.patternProperties == nil || len(s.patternProperties) == 0 {
- return STRING_UNDEFINED // should never happen
- }
-
- patternPropertiesKeySlice := []string{}
- for pk := range s.patternProperties {
- patternPropertiesKeySlice = append(patternPropertiesKeySlice, `"`+pk+`"`)
- }
-
- if len(patternPropertiesKeySlice) == 1 {
- return patternPropertiesKeySlice[0]
- }
-
- return "[" + strings.Join(patternPropertiesKeySlice, ",") + "]"
-
-}
diff --git a/vendor/github.com/xeipuuv/gojsonschema/types.go b/vendor/github.com/xeipuuv/gojsonschema/types.go
index 952d22ef6..0e6fd5173 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/types.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/types.go
@@ -25,6 +25,7 @@
package gojsonschema
+// Type constants
const (
TYPE_ARRAY = `array`
TYPE_BOOLEAN = `boolean`
@@ -35,7 +36,10 @@ const (
TYPE_STRING = `string`
)
+// JSON_TYPES hosts the list of type that are supported in JSON
var JSON_TYPES []string
+
+// SCHEMA_TYPES hosts the list of type that are supported in schemas
var SCHEMA_TYPES []string
func init() {
diff --git a/vendor/github.com/xeipuuv/gojsonschema/utils.go b/vendor/github.com/xeipuuv/gojsonschema/utils.go
index 88d223fbf..a17d22e3b 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/utils.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/utils.go
@@ -27,15 +27,13 @@ package gojsonschema
import (
"encoding/json"
- "fmt"
- "math"
"math/big"
"reflect"
)
func isKind(what interface{}, kinds ...reflect.Kind) bool {
target := what
- if isJsonNumber(what) {
+ if isJSONNumber(what) {
// JSON Numbers are strings!
target = *mustBeNumber(what)
}
@@ -72,7 +70,7 @@ func indexStringInSlice(s []string, what string) int {
return -1
}
-func marshalToJsonString(value interface{}) (*string, error) {
+func marshalToJSONString(value interface{}) (*string, error) {
mBytes, err := json.Marshal(value)
if err != nil {
@@ -90,7 +88,7 @@ func marshalWithoutNumber(value interface{}) (*string, error) {
// One way to eliminate these differences is to decode and encode the JSON one more time without Decoder.UseNumber
// so that these differences in representation are removed
- jsonString, err := marshalToJsonString(value)
+ jsonString, err := marshalToJSONString(value)
if err != nil {
return nil, err
}
@@ -102,10 +100,10 @@ func marshalWithoutNumber(value interface{}) (*string, error) {
return nil, err
}
- return marshalToJsonString(document)
+ return marshalToJSONString(document)
}
-func isJsonNumber(what interface{}) bool {
+func isJSONNumber(what interface{}) bool {
switch what.(type) {
@@ -116,7 +114,7 @@ func isJsonNumber(what interface{}) bool {
return false
}
-func checkJsonInteger(what interface{}) (isInt bool) {
+func checkJSONInteger(what interface{}) (isInt bool) {
jsonNumber := what.(json.Number)
@@ -128,26 +126,17 @@ func checkJsonInteger(what interface{}) (isInt bool) {
// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER
const (
- max_json_float = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
- min_json_float = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
+ maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1
+ minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1
)
-func isFloat64AnInteger(f float64) bool {
-
- if math.IsNaN(f) || math.IsInf(f, 0) || f < min_json_float || f > max_json_float {
- return false
- }
-
- return f == float64(int64(f)) || f == float64(uint64(f))
-}
-
func mustBeInteger(what interface{}) *int {
- if isJsonNumber(what) {
+ if isJSONNumber(what) {
number := what.(json.Number)
- isInt := checkJsonInteger(number)
+ isInt := checkJSONInteger(number)
if isInt {
@@ -158,9 +147,6 @@ func mustBeInteger(what interface{}) *int {
int32Value := int(int64Value)
return &int32Value
-
- } else {
- return nil
}
}
@@ -170,43 +156,18 @@ func mustBeInteger(what interface{}) *int {
func mustBeNumber(what interface{}) *big.Rat {
- if isJsonNumber(what) {
+ if isJSONNumber(what) {
number := what.(json.Number)
float64Value, success := new(big.Rat).SetString(string(number))
if success {
return float64Value
- } else {
- return nil
}
-
}
return nil
}
-// formats a number so that it is displayed as the smallest string possible
-func resultErrorFormatJsonNumber(n json.Number) string {
-
- if int64Value, err := n.Int64(); err == nil {
- return fmt.Sprintf("%d", int64Value)
- }
-
- float64Value, _ := n.Float64()
-
- return fmt.Sprintf("%g", float64Value)
-}
-
-// formats a number so that it is displayed as the smallest string possible
-func resultErrorFormatNumber(n float64) string {
-
- if isFloat64AnInteger(n) {
- return fmt.Sprintf("%d", int64(n))
- }
-
- return fmt.Sprintf("%g", n)
-}
-
func convertDocumentNode(val interface{}) interface{} {
if lval, ok := val.([]interface{}); ok {
diff --git a/vendor/github.com/xeipuuv/gojsonschema/validation.go b/vendor/github.com/xeipuuv/gojsonschema/validation.go
index 090c11e93..74091bca1 100644
--- a/vendor/github.com/xeipuuv/gojsonschema/validation.go
+++ b/vendor/github.com/xeipuuv/gojsonschema/validation.go
@@ -35,42 +35,29 @@ import (
"unicode/utf8"
)
+// Validate loads and validates a JSON schema
func Validate(ls JSONLoader, ld JSONLoader) (*Result, error) {
-
- var err error
-
// load schema
-
schema, err := NewSchema(ls)
if err != nil {
return nil, err
}
-
- // begine validation
-
return schema.Validate(ld)
-
}
+// Validate loads and validates a JSON document
func (v *Schema) Validate(l JSONLoader) (*Result, error) {
-
- // load document
-
root, err := l.LoadJSON()
if err != nil {
return nil, err
}
-
return v.validateDocument(root), nil
}
func (v *Schema) validateDocument(root interface{}) *Result {
- // begin validation
-
result := &Result{}
context := NewJsonContext(STRING_CONTEXT_ROOT, nil)
v.rootSchema.validateRecursive(v.rootSchema, root, result, context)
-
return result
}
@@ -88,6 +75,19 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
internalLog(" %v", currentNode)
}
+ // Handle true/false schema as early as possible as all other fields will be nil
+ if currentSubSchema.pass != nil {
+ if !*currentSubSchema.pass {
+ result.addInternalError(
+ new(FalseError),
+ context,
+ currentNode,
+ ErrorDetails{},
+ )
+ }
+ return
+ }
+
// Handle referenced schemas, returns directly when a $ref is found
if currentSubSchema.refSchema != nil {
v.validateRecursive(currentSubSchema.refSchema, currentNode, result, context)
@@ -114,11 +114,11 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
} else { // Not a null value
- if isJsonNumber(currentNode) {
+ if isJSONNumber(currentNode) {
value := currentNode.(json.Number)
- isInt := checkJsonInteger(value)
+ isInt := checkJSONInteger(value)
validType := currentSubSchema.types.Contains(TYPE_NUMBER) || (isInt && currentSubSchema.types.Contains(TYPE_INTEGER))
@@ -424,11 +424,11 @@ func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{
// enum:
if len(currentSubSchema.enum) > 0 {
- has, err := currentSubSchema.ContainsEnum(value)
+ vString, err := marshalWithoutNumber(value)
if err != nil {
result.addInternalError(new(InternalError), context, value, ErrorDetails{"error": err})
}
- if !has {
+ if !isStringInSlice(currentSubSchema.enum, *vString) {
result.addInternalError(
new(EnumError),
context,
@@ -516,13 +516,13 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
// uniqueItems:
if currentSubSchema.uniqueItems {
- var stringifiedItems []string
+ var stringifiedItems = make(map[string]int)
for j, v := range value {
vString, err := marshalWithoutNumber(v)
if err != nil {
result.addInternalError(new(InternalError), context, value, ErrorDetails{"err": err})
}
- if i := indexStringInSlice(stringifiedItems, *vString); i > -1 {
+ if i, ok := stringifiedItems[*vString]; ok {
result.addInternalError(
new(ItemsMustBeUniqueError),
context,
@@ -530,7 +530,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
ErrorDetails{"type": TYPE_ARRAY, "i": i, "j": j},
)
}
- stringifiedItems = append(stringifiedItems, *vString)
+ stringifiedItems[*vString] = j
}
}
@@ -614,101 +614,37 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
}
// additionalProperty & patternProperty:
- if currentSubSchema.additionalProperties != nil {
-
- switch currentSubSchema.additionalProperties.(type) {
- case bool:
-
- if !currentSubSchema.additionalProperties.(bool) {
-
- for pk := range value {
-
- found := false
- for _, spValue := range currentSubSchema.propertiesChildren {
- if pk == spValue.property {
- found = true
- }
- }
-
- pp_has, pp_match := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)
-
- if found {
-
- if pp_has && !pp_match {
- result.addInternalError(
- new(AdditionalPropertyNotAllowedError),
- context,
- value[pk],
- ErrorDetails{"property": pk},
- )
- }
-
- } else {
-
- if !pp_has || !pp_match {
- result.addInternalError(
- new(AdditionalPropertyNotAllowedError),
- context,
- value[pk],
- ErrorDetails{"property": pk},
- )
- }
-
- }
- }
- }
-
- case *subSchema:
-
- additionalPropertiesSchema := currentSubSchema.additionalProperties.(*subSchema)
- for pk := range value {
-
- found := false
- for _, spValue := range currentSubSchema.propertiesChildren {
- if pk == spValue.property {
- found = true
- }
- }
-
- pp_has, pp_match := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)
-
- if found {
-
- if pp_has && !pp_match {
- validationResult := additionalPropertiesSchema.subValidateWithContext(value[pk], context)
- result.mergeErrors(validationResult)
- }
-
- } else {
-
- if !pp_has || !pp_match {
- validationResult := additionalPropertiesSchema.subValidateWithContext(value[pk], context)
- result.mergeErrors(validationResult)
- }
-
- }
+ for pk := range value {
+ // Check whether this property is described by "properties"
+ found := false
+ for _, spValue := range currentSubSchema.propertiesChildren {
+ if pk == spValue.property {
+ found = true
}
}
- } else {
- for pk := range value {
-
- pp_has, pp_match := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)
+ // Check whether this property is described by "patternProperties"
+ ppMatch := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)
- if pp_has && !pp_match {
+ // If it is not described by neither "properties" nor "patternProperties" it must pass "additionalProperties"
+ if !found && !ppMatch {
+ switch ap := currentSubSchema.additionalProperties.(type) {
+ case bool:
+ // Handle the boolean case separately as it's cleaner to return a specific error than failing to pass the false schema
+ if !ap {
+ result.addInternalError(
+ new(AdditionalPropertyNotAllowedError),
+ context,
+ value[pk],
+ ErrorDetails{"property": pk},
+ )
- result.addInternalError(
- new(InvalidPropertyPatternError),
- context,
- value[pk],
- ErrorDetails{
- "property": pk,
- "pattern": currentSubSchema.PatternPropertiesString(),
- },
- )
+ }
+ case *subSchema:
+ validationResult := ap.subValidateWithContext(value[pk], NewJsonContext(pk, context))
+ result.mergeErrors(validationResult)
}
-
}
}
@@ -730,40 +666,36 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
result.incrementScore()
}
-func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) (has bool, matched bool) {
+func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) bool {
if internalLogEnabled {
internalLog("validatePatternProperty %s", context.String())
internalLog(" %s %v", key, value)
}
- has = false
-
- validatedkey := false
+ validated := false
for pk, pv := range currentSubSchema.patternProperties {
if matches, _ := regexp.MatchString(pk, key); matches {
- has = true
+ validated = true
subContext := NewJsonContext(key, context)
validationResult := pv.subValidateWithContext(value, subContext)
result.mergeErrors(validationResult)
- validatedkey = true
}
}
- if !validatedkey {
- return has, false
+ if !validated {
+ return false
}
result.incrementScore()
-
- return has, true
+ return true
}
func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
// Ignore JSON numbers
- if isJsonNumber(value) {
+ if isJSONNumber(value) {
return
}
@@ -832,7 +764,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
// Ignore non numbers
- if !isJsonNumber(value) {
+ if !isJSONNumber(value) {
return
}
@@ -850,8 +782,10 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
result.addInternalError(
new(MultipleOfError),
context,
- resultErrorFormatJsonNumber(number),
- ErrorDetails{"multiple": new(big.Float).SetRat(currentSubSchema.multipleOf)},
+ number,
+ ErrorDetails{
+ "multiple": new(big.Float).SetRat(currentSubSchema.multipleOf),
+ },
)
}
}
@@ -862,9 +796,9 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
result.addInternalError(
new(NumberLTEError),
context,
- resultErrorFormatJsonNumber(number),
+ number,
ErrorDetails{
- "max": currentSubSchema.maximum,
+ "max": new(big.Float).SetRat(currentSubSchema.maximum),
},
)
}
@@ -874,9 +808,9 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
result.addInternalError(
new(NumberLTError),
context,
- resultErrorFormatJsonNumber(number),
+ number,
ErrorDetails{
- "max": currentSubSchema.exclusiveMaximum,
+ "max": new(big.Float).SetRat(currentSubSchema.exclusiveMaximum),
},
)
}
@@ -888,22 +822,21 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
result.addInternalError(
new(NumberGTEError),
context,
- resultErrorFormatJsonNumber(number),
+ number,
ErrorDetails{
- "min": currentSubSchema.minimum,
+ "min": new(big.Float).SetRat(currentSubSchema.minimum),
},
)
}
}
if currentSubSchema.exclusiveMinimum != nil {
if float64Value.Cmp(currentSubSchema.exclusiveMinimum) <= 0 {
- // if float64Value <= *currentSubSchema.minimum {
result.addInternalError(
new(NumberGTError),
context,
- resultErrorFormatJsonNumber(number),
+ number,
ErrorDetails{
- "min": currentSubSchema.exclusiveMinimum,
+ "min": new(big.Float).SetRat(currentSubSchema.exclusiveMinimum),
},
)
}
diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go
new file mode 100644
index 000000000..9d80f1952
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/block.go
@@ -0,0 +1,159 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package blowfish
+
+// getNextWord returns the next big-endian uint32 value from the byte slice
+// at the given position in a circular manner, updating the position.
+func getNextWord(b []byte, pos *int) uint32 {
+ var w uint32
+ j := *pos
+ for i := 0; i < 4; i++ {
+ w = w<<8 | uint32(b[j])
+ j++
+ if j >= len(b) {
+ j = 0
+ }
+ }
+ *pos = j
+ return w
+}
+
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
+ j := 0
+ for i := 0; i < 18; i++ {
+ // Using inlined getNextWord for performance.
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(key[j])
+ j++
+ if j >= len(key) {
+ j = 0
+ }
+ }
+ c.p[i] ^= d
+ }
+
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+ }
+ for i := 0; i < 256; i += 2 {
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+ }
+}
+
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+ j := 0
+ for i := 0; i < 18; i++ {
+ c.p[i] ^= getNextWord(key, &j)
+ }
+
+ j = 0
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 2 {
+ l ^= getNextWord(salt, &j)
+ r ^= getNextWord(salt, &j)
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+ }
+}
+
+func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+ xl, xr := l, r
+ xl ^= c.p[0]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
+ xr ^= c.p[17]
+ return xr, xl
+}
+
+func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+ xl, xr := l, r
+ xl ^= c.p[17]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
+ xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
+ xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
+ xr ^= c.p[0]
+ return xr, xl
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go
new file mode 100644
index 000000000..213bf204a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/cipher.go
@@ -0,0 +1,99 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
+//
+// Blowfish is a legacy cipher and its short block size makes it vulnerable to
+// birthday bound attacks (see https://sweet32.info). It should only be used
+// where compatibility with legacy systems, not security, is the goal.
+//
+// Deprecated: any new system should use AES (from crypto/aes, if necessary in
+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
+// golang.org/x/crypto/chacha20poly1305).
+package blowfish // import "golang.org/x/crypto/blowfish"
+
+// The code is a port of Bruce Schneier's C implementation.
+// See https://www.schneier.com/blowfish.html.
+
+import "strconv"
+
+// The Blowfish block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of Blowfish encryption using a particular key.
+type Cipher struct {
+ p [18]uint32
+ s0, s1, s2, s3 [256]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+ return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Blowfish key, from 1 to 56 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+ var result Cipher
+ if k := len(key); k < 1 || k > 56 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(&result)
+ ExpandKey(key, &result)
+ return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatibility, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
+ if len(salt) == 0 {
+ return NewCipher(key)
+ }
+ var result Cipher
+ if k := len(key); k < 1 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(&result)
+ expandKeyWithSalt(key, salt, &result)
+ return &result, nil
+}
+
+// BlockSize returns the Blowfish block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+ l, r = encryptBlock(l, r, c)
+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+// Decrypt decrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) {
+ l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+ r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+ l, r = decryptBlock(l, r, c)
+ dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+ dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+func initCipher(c *Cipher) {
+ copy(c.p[0:], p[0:])
+ copy(c.s0[0:], s0[0:])
+ copy(c.s1[0:], s1[0:])
+ copy(c.s2[0:], s2[0:])
+ copy(c.s3[0:], s3[0:])
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go
new file mode 100644
index 000000000..d04077595
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/const.go
@@ -0,0 +1,199 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The startup permutation array and substitution boxes.
+// They are the hexadecimal digits of PI; see:
+// https://www.schneier.com/code/constants.txt.
+
+package blowfish
+
+var s0 = [256]uint32{
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+ 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
+ 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
+ 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+ 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
+ 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
+ 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+ 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
+ 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
+ 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+ 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
+ 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
+ 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+ 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
+ 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
+ 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+ 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
+ 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
+ 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+ 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
+ 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
+ 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+}
+
+var s1 = [256]uint32{
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+ 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+ 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+ 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+ 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+ 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+ 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+ 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+ 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+ 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+ 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+ 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+ 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+ 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+ 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+ 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+ 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+ 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+ 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+ 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+ 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+ 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+}
+
+var s2 = [256]uint32{
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
+ 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+ 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
+ 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+ 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+ 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
+ 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
+ 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
+ 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+ 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
+ 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+ 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
+ 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+ 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+ 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+ 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+ 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+ 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
+ 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+ 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
+ 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+ 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+}
+
+var s3 = [256]uint32{
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+ 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+ 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+ 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
+ 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+ 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
+ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+ 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+ 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
+ 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+ 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+ 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+ 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+ 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+ 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+}
+
+var p = [18]uint32{
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
+}
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
index 592d18643..36a680436 100644
--- a/vendor/golang.org/x/crypto/openpgp/armor/armor.go
+++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
@@ -62,10 +62,11 @@ var armorEndOfLine = []byte("-----")
// lineReader wraps a line based reader. It watches for the end of an armor
// block and records the expected CRC value.
type lineReader struct {
- in *bufio.Reader
- buf []byte
- eof bool
- crc uint32
+ in *bufio.Reader
+ buf []byte
+ eof bool
+ crc uint32
+ crcSet bool
}
func (l *lineReader) Read(p []byte) (n int, err error) {
@@ -87,6 +88,11 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
return 0, ArmorCorrupt
}
+ if bytes.HasPrefix(line, armorEnd) {
+ l.eof = true
+ return 0, io.EOF
+ }
+
if len(line) == 5 && line[0] == '=' {
// This is the checksum line
var expectedBytes [3]byte
@@ -108,6 +114,7 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
}
l.eof = true
+ l.crcSet = true
return 0, io.EOF
}
@@ -141,10 +148,8 @@ func (r *openpgpReader) Read(p []byte) (n int, err error) {
n, err = r.b64Reader.Read(p)
r.currentCRC = crc24(r.currentCRC, p[:n])
- if err == io.EOF {
- if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
- return 0, ArmorCorrupt
- }
+ if err == io.EOF && r.lReader.crcSet && r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
+ return 0, ArmorCorrupt
}
return
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/golang.org/x/crypto/poly1305/sum_arm.go
deleted file mode 100644
index 6e695e427..000000000
--- a/vendor/golang.org/x/crypto/poly1305/sum_arm.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build arm,!gccgo,!appengine,!nacl
-
-package poly1305
-
-// poly1305_auth_armv6 is implemented in sum_arm.s
-//go:noescape
-func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
-
-func sum(out *[16]byte, m []byte, key *[32]byte) {
- var mPtr *byte
- if len(m) > 0 {
- mPtr = &m[0]
- }
- poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
-}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/golang.org/x/crypto/poly1305/sum_arm.s
deleted file mode 100644
index f70b4ac48..000000000
--- a/vendor/golang.org/x/crypto/poly1305/sum_arm.s
+++ /dev/null
@@ -1,427 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build arm,!gccgo,!appengine,!nacl
-
-#include "textflag.h"
-
-// This code was translated into a form compatible with 5a from the public
-// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
-
-DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
-DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
-DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
-DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
-DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
-GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
-
-// Warning: the linker may use R11 to synthesize certain instructions. Please
-// take care and verify that no synthetic instructions use it.
-
-TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
- // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
- // might look like it's only 60 bytes of space but the final four bytes
- // will be written by another function.) We need to skip over four
- // bytes of stack because that's saving the value of 'g'.
- ADD $4, R13, R8
- MOVM.IB [R4-R7], (R8)
- MOVM.IA.W (R1), [R2-R5]
- MOVW $·poly1305_init_constants_armv6<>(SB), R7
- MOVW R2, R8
- MOVW R2>>26, R9
- MOVW R3>>20, g
- MOVW R4>>14, R11
- MOVW R5>>8, R12
- ORR R3<<6, R9, R9
- ORR R4<<12, g, g
- ORR R5<<18, R11, R11
- MOVM.IA (R7), [R2-R6]
- AND R8, R2, R2
- AND R9, R3, R3
- AND g, R4, R4
- AND R11, R5, R5
- AND R12, R6, R6
- MOVM.IA.W [R2-R6], (R0)
- EOR R2, R2, R2
- EOR R3, R3, R3
- EOR R4, R4, R4
- EOR R5, R5, R5
- EOR R6, R6, R6
- MOVM.IA.W [R2-R6], (R0)
- MOVM.IA.W (R1), [R2-R5]
- MOVM.IA [R2-R6], (R0)
- ADD $20, R13, R0
- MOVM.DA (R0), [R4-R7]
- RET
-
-#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
- MOVBU (offset+0)(Rsrc), Rtmp; \
- MOVBU Rtmp, (offset+0)(Rdst); \
- MOVBU (offset+1)(Rsrc), Rtmp; \
- MOVBU Rtmp, (offset+1)(Rdst); \
- MOVBU (offset+2)(Rsrc), Rtmp; \
- MOVBU Rtmp, (offset+2)(Rdst); \
- MOVBU (offset+3)(Rsrc), Rtmp; \
- MOVBU Rtmp, (offset+3)(Rdst)
-
-TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
- // Needs 24 bytes of stack for saved registers and then 88 bytes of
- // scratch space after that. We assume that 24 bytes at (R13) have
- // already been used: four bytes for the link register saved in the
- // prelude of poly1305_auth_armv6, four bytes for saving the value of g
- // in that function and 16 bytes of scratch space used around
- // poly1305_finish_ext_armv6_skip1.
- ADD $24, R13, R12
- MOVM.IB [R4-R8, R14], (R12)
- MOVW R0, 88(R13)
- MOVW R1, 92(R13)
- MOVW R2, 96(R13)
- MOVW R1, R14
- MOVW R2, R12
- MOVW 56(R0), R8
- WORD $0xe1180008 // TST R8, R8 not working see issue 5921
- EOR R6, R6, R6
- MOVW.EQ $(1<<24), R6
- MOVW R6, 84(R13)
- ADD $116, R13, g
- MOVM.IA (R0), [R0-R9]
- MOVM.IA [R0-R4], (g)
- CMP $16, R12
- BLO poly1305_blocks_armv6_done
-
-poly1305_blocks_armv6_mainloop:
- WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
- BEQ poly1305_blocks_armv6_mainloop_aligned
- ADD $100, R13, g
- MOVW_UNALIGNED(R14, g, R0, 0)
- MOVW_UNALIGNED(R14, g, R0, 4)
- MOVW_UNALIGNED(R14, g, R0, 8)
- MOVW_UNALIGNED(R14, g, R0, 12)
- MOVM.IA (g), [R0-R3]
- ADD $16, R14
- B poly1305_blocks_armv6_mainloop_loaded
-
-poly1305_blocks_armv6_mainloop_aligned:
- MOVM.IA.W (R14), [R0-R3]
-
-poly1305_blocks_armv6_mainloop_loaded:
- MOVW R0>>26, g
- MOVW R1>>20, R11
- MOVW R2>>14, R12
- MOVW R14, 92(R13)
- MOVW R3>>8, R4
- ORR R1<<6, g, g
- ORR R2<<12, R11, R11
- ORR R3<<18, R12, R12
- BIC $0xfc000000, R0, R0
- BIC $0xfc000000, g, g
- MOVW 84(R13), R3
- BIC $0xfc000000, R11, R11
- BIC $0xfc000000, R12, R12
- ADD R0, R5, R5
- ADD g, R6, R6
- ORR R3, R4, R4
- ADD R11, R7, R7
- ADD $116, R13, R14
- ADD R12, R8, R8
- ADD R4, R9, R9
- MOVM.IA (R14), [R0-R4]
- MULLU R4, R5, (R11, g)
- MULLU R3, R5, (R14, R12)
- MULALU R3, R6, (R11, g)
- MULALU R2, R6, (R14, R12)
- MULALU R2, R7, (R11, g)
- MULALU R1, R7, (R14, R12)
- ADD R4<<2, R4, R4
- ADD R3<<2, R3, R3
- MULALU R1, R8, (R11, g)
- MULALU R0, R8, (R14, R12)
- MULALU R0, R9, (R11, g)
- MULALU R4, R9, (R14, R12)
- MOVW g, 76(R13)
- MOVW R11, 80(R13)
- MOVW R12, 68(R13)
- MOVW R14, 72(R13)
- MULLU R2, R5, (R11, g)
- MULLU R1, R5, (R14, R12)
- MULALU R1, R6, (R11, g)
- MULALU R0, R6, (R14, R12)
- MULALU R0, R7, (R11, g)
- MULALU R4, R7, (R14, R12)
- ADD R2<<2, R2, R2
- ADD R1<<2, R1, R1
- MULALU R4, R8, (R11, g)
- MULALU R3, R8, (R14, R12)
- MULALU R3, R9, (R11, g)
- MULALU R2, R9, (R14, R12)
- MOVW g, 60(R13)
- MOVW R11, 64(R13)
- MOVW R12, 52(R13)
- MOVW R14, 56(R13)
- MULLU R0, R5, (R11, g)
- MULALU R4, R6, (R11, g)
- MULALU R3, R7, (R11, g)
- MULALU R2, R8, (R11, g)
- MULALU R1, R9, (R11, g)
- ADD $52, R13, R0
- MOVM.IA (R0), [R0-R7]
- MOVW g>>26, R12
- MOVW R4>>26, R14
- ORR R11<<6, R12, R12
- ORR R5<<6, R14, R14
- BIC $0xfc000000, g, g
- BIC $0xfc000000, R4, R4
- ADD.S R12, R0, R0
- ADC $0, R1, R1
- ADD.S R14, R6, R6
- ADC $0, R7, R7
- MOVW R0>>26, R12
- MOVW R6>>26, R14
- ORR R1<<6, R12, R12
- ORR R7<<6, R14, R14
- BIC $0xfc000000, R0, R0
- BIC $0xfc000000, R6, R6
- ADD R14<<2, R14, R14
- ADD.S R12, R2, R2
- ADC $0, R3, R3
- ADD R14, g, g
- MOVW R2>>26, R12
- MOVW g>>26, R14
- ORR R3<<6, R12, R12
- BIC $0xfc000000, g, R5
- BIC $0xfc000000, R2, R7
- ADD R12, R4, R4
- ADD R14, R0, R0
- MOVW R4>>26, R12
- BIC $0xfc000000, R4, R8
- ADD R12, R6, R9
- MOVW 96(R13), R12
- MOVW 92(R13), R14
- MOVW R0, R6
- CMP $32, R12
- SUB $16, R12, R12
- MOVW R12, 96(R13)
- BHS poly1305_blocks_armv6_mainloop
-
-poly1305_blocks_armv6_done:
- MOVW 88(R13), R12
- MOVW R5, 20(R12)
- MOVW R6, 24(R12)
- MOVW R7, 28(R12)
- MOVW R8, 32(R12)
- MOVW R9, 36(R12)
- ADD $48, R13, R0
- MOVM.DA (R0), [R4-R8, R14]
- RET
-
-#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
- MOVBU.P 1(Rsrc), Rtmp; \
- MOVBU.P Rtmp, 1(Rdst); \
- MOVBU.P 1(Rsrc), Rtmp; \
- MOVBU.P Rtmp, 1(Rdst)
-
-#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
- MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
- MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
-
-// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
-TEXT ·poly1305_auth_armv6(SB), $196-16
- // The value 196, just above, is the sum of 64 (the size of the context
- // structure) and 132 (the amount of stack needed).
- //
- // At this point, the stack pointer (R13) has been moved down. It
- // points to the saved link register and there's 196 bytes of free
- // space above it.
- //
- // The stack for this function looks like:
- //
- // +---------------------
- // |
- // | 64 bytes of context structure
- // |
- // +---------------------
- // |
- // | 112 bytes for poly1305_blocks_armv6
- // |
- // +---------------------
- // | 16 bytes of final block, constructed at
- // | poly1305_finish_ext_armv6_skip8
- // +---------------------
- // | four bytes of saved 'g'
- // +---------------------
- // | lr, saved by prelude <- R13 points here
- // +---------------------
- MOVW g, 4(R13)
-
- MOVW out+0(FP), R4
- MOVW m+4(FP), R5
- MOVW mlen+8(FP), R6
- MOVW key+12(FP), R7
-
- ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
- MOVW R7, R1
-
- // poly1305_init_ext_armv6 will write to the stack from R13+4, but
- // that's ok because none of the other values have been written yet.
- BL poly1305_init_ext_armv6<>(SB)
- BIC.S $15, R6, R2
- BEQ poly1305_auth_armv6_noblocks
- ADD $136, R13, R0
- MOVW R5, R1
- ADD R2, R5, R5
- SUB R2, R6, R6
- BL poly1305_blocks_armv6<>(SB)
-
-poly1305_auth_armv6_noblocks:
- ADD $136, R13, R0
- MOVW R5, R1
- MOVW R6, R2
- MOVW R4, R3
-
- MOVW R0, R5
- MOVW R1, R6
- MOVW R2, R7
- MOVW R3, R8
- AND.S R2, R2, R2
- BEQ poly1305_finish_ext_armv6_noremaining
- EOR R0, R0
- ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
- MOVW R0, (R9)
- MOVW R0, 4(R9)
- MOVW R0, 8(R9)
- MOVW R0, 12(R9)
- WORD $0xe3110003 // TST R1, #3 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_aligned
- WORD $0xe3120008 // TST R2, #8 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip8
- MOVWP_UNALIGNED(R1, R9, g)
- MOVWP_UNALIGNED(R1, R9, g)
-
-poly1305_finish_ext_armv6_skip8:
- WORD $0xe3120004 // TST $4, R2 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip4
- MOVWP_UNALIGNED(R1, R9, g)
-
-poly1305_finish_ext_armv6_skip4:
- WORD $0xe3120002 // TST $2, R2 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip2
- MOVHUP_UNALIGNED(R1, R9, g)
- B poly1305_finish_ext_armv6_skip2
-
-poly1305_finish_ext_armv6_aligned:
- WORD $0xe3120008 // TST R2, #8 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip8_aligned
- MOVM.IA.W (R1), [g-R11]
- MOVM.IA.W [g-R11], (R9)
-
-poly1305_finish_ext_armv6_skip8_aligned:
- WORD $0xe3120004 // TST $4, R2 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip4_aligned
- MOVW.P 4(R1), g
- MOVW.P g, 4(R9)
-
-poly1305_finish_ext_armv6_skip4_aligned:
- WORD $0xe3120002 // TST $2, R2 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip2
- MOVHU.P 2(R1), g
- MOVH.P g, 2(R9)
-
-poly1305_finish_ext_armv6_skip2:
- WORD $0xe3120001 // TST $1, R2 not working see issue 5921
- BEQ poly1305_finish_ext_armv6_skip1
- MOVBU.P 1(R1), g
- MOVBU.P g, 1(R9)
-
-poly1305_finish_ext_armv6_skip1:
- MOVW $1, R11
- MOVBU R11, 0(R9)
- MOVW R11, 56(R5)
- MOVW R5, R0
- ADD $8, R13, R1
- MOVW $16, R2
- BL poly1305_blocks_armv6<>(SB)
-
-poly1305_finish_ext_armv6_noremaining:
- MOVW 20(R5), R0
- MOVW 24(R5), R1
- MOVW 28(R5), R2
- MOVW 32(R5), R3
- MOVW 36(R5), R4
- MOVW R4>>26, R12
- BIC $0xfc000000, R4, R4
- ADD R12<<2, R12, R12
- ADD R12, R0, R0
- MOVW R0>>26, R12
- BIC $0xfc000000, R0, R0
- ADD R12, R1, R1
- MOVW R1>>26, R12
- BIC $0xfc000000, R1, R1
- ADD R12, R2, R2
- MOVW R2>>26, R12
- BIC $0xfc000000, R2, R2
- ADD R12, R3, R3
- MOVW R3>>26, R12
- BIC $0xfc000000, R3, R3
- ADD R12, R4, R4
- ADD $5, R0, R6
- MOVW R6>>26, R12
- BIC $0xfc000000, R6, R6
- ADD R12, R1, R7
- MOVW R7>>26, R12
- BIC $0xfc000000, R7, R7
- ADD R12, R2, g
- MOVW g>>26, R12
- BIC $0xfc000000, g, g
- ADD R12, R3, R11
- MOVW $-(1<<26), R12
- ADD R11>>26, R12, R12
- BIC $0xfc000000, R11, R11
- ADD R12, R4, R9
- MOVW R9>>31, R12
- SUB $1, R12
- AND R12, R6, R6
- AND R12, R7, R7
- AND R12, g, g
- AND R12, R11, R11
- AND R12, R9, R9
- MVN R12, R12
- AND R12, R0, R0
- AND R12, R1, R1
- AND R12, R2, R2
- AND R12, R3, R3
- AND R12, R4, R4
- ORR R6, R0, R0
- ORR R7, R1, R1
- ORR g, R2, R2
- ORR R11, R3, R3
- ORR R9, R4, R4
- ORR R1<<26, R0, R0
- MOVW R1>>6, R1
- ORR R2<<20, R1, R1
- MOVW R2>>12, R2
- ORR R3<<14, R2, R2
- MOVW R3>>18, R3
- ORR R4<<8, R3, R3
- MOVW 40(R5), R6
- MOVW 44(R5), R7
- MOVW 48(R5), g
- MOVW 52(R5), R11
- ADD.S R6, R0, R0
- ADC.S R7, R1, R1
- ADC.S g, R2, R2
- ADC.S R11, R3, R3
- MOVM.IA [R0-R3], (R8)
- MOVW R5, R12
- EOR R0, R0, R0
- EOR R1, R1, R1
- EOR R2, R2, R2
- EOR R3, R3, R3
- EOR R4, R4, R4
- EOR R5, R5, R5
- EOR R6, R6, R6
- EOR R7, R7, R7
- MOVM.IA.W [R0-R7], (R12)
- MOVM.IA [R0-R7], (R12)
- MOVW 4(R13), g
- RET
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go
index 1682eda45..32a9cef6b 100644
--- a/vendor/golang.org/x/crypto/poly1305/sum_noasm.go
+++ b/vendor/golang.org/x/crypto/poly1305/sum_noasm.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build s390x,!go1.11 !arm,!amd64,!s390x,!ppc64le gccgo appengine nacl
+// +build s390x,!go1.11 !amd64,!s390x,!ppc64le gccgo appengine nacl
package poly1305
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 00ed9923e..0f89aec1c 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -17,12 +17,14 @@ import (
// These constants from [PROTOCOL.certkeys] represent the algorithm names
// for certificate types supported by this package.
const (
- CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
- CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
- CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
- CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
- CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
- CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
+ CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
+ CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
+ CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
+ CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
+ CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
+ CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
)
// Certificate types distinguish between host and user
@@ -37,6 +39,7 @@ const (
type Signature struct {
Format string
Blob []byte
+ Rest []byte `ssh:"rest"`
}
// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
@@ -429,12 +432,14 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
}
var certAlgoNames = map[string]string{
- KeyAlgoRSA: CertAlgoRSAv01,
- KeyAlgoDSA: CertAlgoDSAv01,
- KeyAlgoECDSA256: CertAlgoECDSA256v01,
- KeyAlgoECDSA384: CertAlgoECDSA384v01,
- KeyAlgoECDSA521: CertAlgoECDSA521v01,
- KeyAlgoED25519: CertAlgoED25519v01,
+ KeyAlgoRSA: CertAlgoRSAv01,
+ KeyAlgoDSA: CertAlgoDSAv01,
+ KeyAlgoECDSA256: CertAlgoECDSA256v01,
+ KeyAlgoECDSA384: CertAlgoECDSA384v01,
+ KeyAlgoECDSA521: CertAlgoECDSA521v01,
+ KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01,
+ KeyAlgoED25519: CertAlgoED25519v01,
+ KeyAlgoSKED25519: CertAlgoSKED25519v01,
}
// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
@@ -518,6 +523,12 @@ func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
return
}
+ switch out.Format {
+ case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01:
+ out.Rest = in
+ return out, nil, ok
+ }
+
return out, in, ok
}
diff --git a/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
new file mode 100644
index 000000000..af81d2665
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
@@ -0,0 +1,93 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
+//
+// See https://flak.tedunangst.com/post/bcrypt-pbkdf and
+// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c.
+package bcrypt_pbkdf
+
+import (
+ "crypto/sha512"
+ "errors"
+ "golang.org/x/crypto/blowfish"
+)
+
+const blockSize = 32
+
+// Key derives a key from the password, salt and rounds count, returning a
+// []byte of length keyLen that can be used as cryptographic key.
+func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) {
+ if rounds < 1 {
+ return nil, errors.New("bcrypt_pbkdf: number of rounds is too small")
+ }
+ if len(password) == 0 {
+ return nil, errors.New("bcrypt_pbkdf: empty password")
+ }
+ if len(salt) == 0 || len(salt) > 1<<20 {
+ return nil, errors.New("bcrypt_pbkdf: bad salt length")
+ }
+ if keyLen > 1024 {
+ return nil, errors.New("bcrypt_pbkdf: keyLen is too large")
+ }
+
+ numBlocks := (keyLen + blockSize - 1) / blockSize
+ key := make([]byte, numBlocks*blockSize)
+
+ h := sha512.New()
+ h.Write(password)
+ shapass := h.Sum(nil)
+
+ shasalt := make([]byte, 0, sha512.Size)
+ cnt, tmp := make([]byte, 4), make([]byte, blockSize)
+ for block := 1; block <= numBlocks; block++ {
+ h.Reset()
+ h.Write(salt)
+ cnt[0] = byte(block >> 24)
+ cnt[1] = byte(block >> 16)
+ cnt[2] = byte(block >> 8)
+ cnt[3] = byte(block)
+ h.Write(cnt)
+ bcryptHash(tmp, shapass, h.Sum(shasalt))
+
+ out := make([]byte, blockSize)
+ copy(out, tmp)
+ for i := 2; i <= rounds; i++ {
+ h.Reset()
+ h.Write(tmp)
+ bcryptHash(tmp, shapass, h.Sum(shasalt))
+ for j := 0; j < len(out); j++ {
+ out[j] ^= tmp[j]
+ }
+ }
+
+ for i, v := range out {
+ key[i*numBlocks+(block-1)] = v
+ }
+ }
+ return key[:keyLen], nil
+}
+
+var magic = []byte("OxychromaticBlowfishSwatDynamite")
+
+func bcryptHash(out, shapass, shasalt []byte) {
+ c, err := blowfish.NewSaltedCipher(shapass, shasalt)
+ if err != nil {
+ panic(err)
+ }
+ for i := 0; i < 64; i++ {
+ blowfish.ExpandKey(shasalt, c)
+ blowfish.ExpandKey(shapass, c)
+ }
+ copy(out, magic)
+ for i := 0; i < 32; i += 8 {
+ for j := 0; j < 64; j++ {
+ c.Encrypt(out[i:i+8], out[i:i+8])
+ }
+ }
+ // Swap bytes due to different endianness.
+ for i := 0; i < 32; i += 4 {
+ out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3]
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index 969804794..06f537c13 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -7,6 +7,8 @@ package ssh
import (
"bytes"
"crypto"
+ "crypto/aes"
+ "crypto/cipher"
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
@@ -25,17 +27,20 @@ import (
"strings"
"golang.org/x/crypto/ed25519"
+ "golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
)
// These constants represent the algorithm names for key types supported by this
// package.
const (
- KeyAlgoRSA = "ssh-rsa"
- KeyAlgoDSA = "ssh-dss"
- KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
- KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
- KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
- KeyAlgoED25519 = "ssh-ed25519"
+ KeyAlgoRSA = "ssh-rsa"
+ KeyAlgoDSA = "ssh-dss"
+ KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
+ KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
+ KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
+ KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
+ KeyAlgoED25519 = "ssh-ed25519"
+ KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
)
// These constants represent non-default signature algorithms that are supported
@@ -58,9 +63,13 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
return parseDSA(in)
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
return parseECDSA(in)
+ case KeyAlgoSKECDSA256:
+ return parseSKECDSA(in)
case KeyAlgoED25519:
return parseED25519(in)
- case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
+ case KeyAlgoSKED25519:
+ return parseSKEd25519(in)
+ case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
cert, err := parseCert(in, certToPrivAlgo(algo))
if err != nil {
return nil, nil, err
@@ -553,9 +562,11 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err
}
- key := ed25519.PublicKey(w.KeyBytes)
+ if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
+ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
+ }
- return (ed25519PublicKey)(key), w.Rest, nil
+ return ed25519PublicKey(w.KeyBytes), w.Rest, nil
}
func (k ed25519PublicKey) Marshal() []byte {
@@ -573,9 +584,11 @@ func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
+ if l := len(k); l != ed25519.PublicKeySize {
+ return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
+ }
- edKey := (ed25519.PublicKey)(k)
- if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
+ if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok {
return errors.New("ssh: signature did not verify")
}
@@ -685,6 +698,224 @@ func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
return (*ecdsa.PublicKey)(k)
}
+// skFields holds the additional fields present in U2F/FIDO2 signatures.
+// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
+type skFields struct {
+ // Flags contains U2F/FIDO2 flags such as 'user present'
+ Flags byte
+ // Counter is a monotonic signature counter which can be
+ // used to detect concurrent use of a private key, should
+ // it be extracted from hardware.
+ Counter uint32
+}
+
+type skECDSAPublicKey struct {
+ // application is a URL-like string, typically "ssh:" for SSH.
+ // see openssh/PROTOCOL.u2f for details.
+ application string
+ ecdsa.PublicKey
+}
+
+func (k *skECDSAPublicKey) Type() string {
+ return KeyAlgoSKECDSA256
+}
+
+func (k *skECDSAPublicKey) nistID() string {
+ return "nistp256"
+}
+
+func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ Curve string
+ KeyBytes []byte
+ Application string
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := new(skECDSAPublicKey)
+ key.application = w.Application
+
+ if w.Curve != "nistp256" {
+ return nil, nil, errors.New("ssh: unsupported curve")
+ }
+ key.Curve = elliptic.P256()
+
+ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
+ if key.X == nil || key.Y == nil {
+ return nil, nil, errors.New("ssh: invalid curve point")
+ }
+
+ return key, w.Rest, nil
+}
+
+func (k *skECDSAPublicKey) Marshal() []byte {
+ // See RFC 5656, section 3.1.
+ keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
+ w := struct {
+ Name string
+ ID string
+ Key []byte
+ Application string
+ }{
+ k.Type(),
+ k.nistID(),
+ keyBytes,
+ k.application,
+ }
+
+ return Marshal(&w)
+}
+
+func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+ }
+
+ h := ecHash(k.Curve).New()
+ h.Write([]byte(k.application))
+ appDigest := h.Sum(nil)
+
+ h.Reset()
+ h.Write(data)
+ dataDigest := h.Sum(nil)
+
+ var ecSig struct {
+ R *big.Int
+ S *big.Int
+ }
+ if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+ return err
+ }
+
+ var skf skFields
+ if err := Unmarshal(sig.Rest, &skf); err != nil {
+ return err
+ }
+
+ blob := struct {
+ ApplicationDigest []byte `ssh:"rest"`
+ Flags byte
+ Counter uint32
+ MessageDigest []byte `ssh:"rest"`
+ }{
+ appDigest,
+ skf.Flags,
+ skf.Counter,
+ dataDigest,
+ }
+
+ original := Marshal(blob)
+
+ h.Reset()
+ h.Write(original)
+ digest := h.Sum(nil)
+
+ if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) {
+ return nil
+ }
+ return errors.New("ssh: signature did not verify")
+}
+
+type skEd25519PublicKey struct {
+ // application is a URL-like string, typically "ssh:" for SSH.
+ // see openssh/PROTOCOL.u2f for details.
+ application string
+ ed25519.PublicKey
+}
+
+func (k *skEd25519PublicKey) Type() string {
+ return KeyAlgoSKED25519
+}
+
+func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ KeyBytes []byte
+ Application string
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
+ return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
+ }
+
+ key := new(skEd25519PublicKey)
+ key.application = w.Application
+ key.PublicKey = ed25519.PublicKey(w.KeyBytes)
+
+ return key, w.Rest, nil
+}
+
+func (k *skEd25519PublicKey) Marshal() []byte {
+ w := struct {
+ Name string
+ KeyBytes []byte
+ Application string
+ }{
+ KeyAlgoSKED25519,
+ []byte(k.PublicKey),
+ k.application,
+ }
+ return Marshal(&w)
+}
+
+func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+ }
+ if l := len(k.PublicKey); l != ed25519.PublicKeySize {
+ return fmt.Errorf("invalid size %d for Ed25519 public key", l)
+ }
+
+ h := sha256.New()
+ h.Write([]byte(k.application))
+ appDigest := h.Sum(nil)
+
+ h.Reset()
+ h.Write(data)
+ dataDigest := h.Sum(nil)
+
+ var edSig struct {
+ Signature []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(sig.Blob, &edSig); err != nil {
+ return err
+ }
+
+ var skf skFields
+ if err := Unmarshal(sig.Rest, &skf); err != nil {
+ return err
+ }
+
+ blob := struct {
+ ApplicationDigest []byte `ssh:"rest"`
+ Flags byte
+ Counter uint32
+ MessageDigest []byte `ssh:"rest"`
+ }{
+ appDigest,
+ skf.Flags,
+ skf.Counter,
+ dataDigest,
+ }
+
+ original := Marshal(blob)
+
+ if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok {
+ return errors.New("ssh: signature did not verify")
+ }
+
+ return nil
+}
+
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
// *ecdsa.PrivateKey or any other crypto.Signer and returns a
// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
@@ -830,14 +1061,18 @@ func NewPublicKey(key interface{}) (PublicKey, error) {
case *dsa.PublicKey:
return (*dsaPublicKey)(key), nil
case ed25519.PublicKey:
- return (ed25519PublicKey)(key), nil
+ if l := len(key); l != ed25519.PublicKeySize {
+ return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
+ }
+ return ed25519PublicKey(key), nil
default:
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
}
}
// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
-// the same keys as ParseRawPrivateKey.
+// the same keys as ParseRawPrivateKey. If the private key is encrypted, it
+// will return a PassphraseMissingError.
func ParsePrivateKey(pemBytes []byte) (Signer, error) {
key, err := ParseRawPrivateKey(pemBytes)
if err != nil {
@@ -850,8 +1085,8 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
// key and passphrase. It supports the same keys as
// ParseRawPrivateKeyWithPassphrase.
-func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
- key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase)
if err != nil {
return nil, err
}
@@ -867,8 +1102,21 @@ func encryptedBlock(block *pem.Block) bool {
return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
}
+// A PassphraseMissingError indicates that parsing this private key requires a
+// passphrase. Use ParsePrivateKeyWithPassphrase.
+type PassphraseMissingError struct {
+ // PublicKey will be set if the private key format includes an unencrypted
+ // public key along with the encrypted private key.
+ PublicKey PublicKey
+}
+
+func (*PassphraseMissingError) Error() string {
+ return "ssh: this private key is passphrase protected"
+}
+
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
-// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys.
+// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the
+// private key is encrypted, it will return a PassphraseMissingError.
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
@@ -876,7 +1124,7 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
}
if encryptedBlock(block) {
- return nil, errors.New("ssh: cannot decode encrypted private keys")
+ return nil, &PassphraseMissingError{}
}
switch block.Type {
@@ -890,33 +1138,35 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
case "DSA PRIVATE KEY":
return ParseDSAPrivateKey(block.Bytes)
case "OPENSSH PRIVATE KEY":
- return parseOpenSSHPrivateKey(block.Bytes)
+ return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey)
default:
return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
}
}
// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
-// passphrase from a PEM encoded private key. If wrong passphrase, return
-// x509.IncorrectPasswordError.
-func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+// passphrase from a PEM encoded private key. If the passphrase is wrong, it
+// will return x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, errors.New("ssh: no key found")
}
- buf := block.Bytes
- if encryptedBlock(block) {
- if x509.IsEncryptedPEMBlock(block) {
- var err error
- buf, err = x509.DecryptPEMBlock(block, passPhrase)
- if err != nil {
- if err == x509.IncorrectPasswordError {
- return nil, err
- }
- return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
- }
+ if block.Type == "OPENSSH PRIVATE KEY" {
+ return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase))
+ }
+
+ if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) {
+ return nil, errors.New("ssh: not an encrypted key")
+ }
+
+ buf, err := x509.DecryptPEMBlock(block, passphrase)
+ if err != nil {
+ if err == x509.IncorrectPasswordError {
+ return nil, err
}
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
}
switch block.Type {
@@ -926,8 +1176,6 @@ func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{},
return x509.ParseECPrivateKey(buf)
case "DSA PRIVATE KEY":
return ParseDSAPrivateKey(buf)
- case "OPENSSH PRIVATE KEY":
- return parseOpenSSHPrivateKey(buf)
default:
return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
}
@@ -965,9 +1213,60 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
}, nil
}
-// Implemented based on the documentation at
-// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
-func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
+func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
+ if kdfName != "none" || cipherName != "none" {
+ return nil, &PassphraseMissingError{}
+ }
+ if kdfOpts != "" {
+ return nil, errors.New("ssh: invalid openssh private key")
+ }
+ return privKeyBlock, nil
+}
+
+func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
+ return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
+ if kdfName == "none" || cipherName == "none" {
+ return nil, errors.New("ssh: key is not password protected")
+ }
+ if kdfName != "bcrypt" {
+ return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt")
+ }
+
+ var opts struct {
+ Salt string
+ Rounds uint32
+ }
+ if err := Unmarshal([]byte(kdfOpts), &opts); err != nil {
+ return nil, err
+ }
+
+ k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
+ if err != nil {
+ return nil, err
+ }
+ key, iv := k[:32], k[32:]
+
+ if cipherName != "aes256-ctr" {
+ return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q", cipherName, "aes256-ctr")
+ }
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ ctr := cipher.NewCTR(c, iv)
+ ctr.XORKeyStream(privKeyBlock, privKeyBlock)
+
+ return privKeyBlock, nil
+ }
+}
+
+type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
+
+// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt
+// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used
+// as the decrypt function to parse an unencrypted private key. See
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
+func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) {
const magic = "openssh-key-v1\x00"
if len(key) < len(magic) || string(key[:len(magic)]) != magic {
return nil, errors.New("ssh: invalid openssh private key format")
@@ -986,9 +1285,22 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
if err := Unmarshal(remaining, &w); err != nil {
return nil, err
}
+ if w.NumKeys != 1 {
+ // We only support single key files, and so does OpenSSH.
+ // https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
+ return nil, errors.New("ssh: multi-key files are not supported")
+ }
- if w.KdfName != "none" || w.CipherName != "none" {
- return nil, errors.New("ssh: cannot decode encrypted private keys")
+ privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock)
+ if err != nil {
+ if err, ok := err.(*PassphraseMissingError); ok {
+ pub, errPub := ParsePublicKey(w.PubKey)
+ if errPub != nil {
+ return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub)
+ }
+ err.PublicKey = pub
+ }
+ return nil, err
}
pk1 := struct {
@@ -998,15 +1310,13 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
Rest []byte `ssh:"rest"`
}{}
- if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
- return nil, err
- }
-
- if pk1.Check1 != pk1.Check2 {
- return nil, errors.New("ssh: checkint mismatch")
+ if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 {
+ if w.CipherName != "none" {
+ return nil, x509.IncorrectPasswordError
+ }
+ return nil, errors.New("ssh: malformed OpenSSH key")
}
- // we only handle ed25519 and rsa keys currently
switch pk1.Keytype {
case KeyAlgoRSA:
// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
@@ -1025,10 +1335,8 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
return nil, err
}
- for i, b := range key.Pad {
- if int(b) != i+1 {
- return nil, errors.New("ssh: padding not as expected")
- }
+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+ return nil, err
}
pk := &rsa.PrivateKey{
@@ -1063,20 +1371,78 @@ func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
return nil, errors.New("ssh: private key unexpected length")
}
- for i, b := range key.Pad {
- if int(b) != i+1 {
- return nil, errors.New("ssh: padding not as expected")
- }
+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+ return nil, err
}
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
copy(pk, key.Priv)
return &pk, nil
+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+ key := struct {
+ Curve string
+ Pub []byte
+ D *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+ return nil, err
+ }
+
+ var curve elliptic.Curve
+ switch key.Curve {
+ case "nistp256":
+ curve = elliptic.P256()
+ case "nistp384":
+ curve = elliptic.P384()
+ case "nistp521":
+ curve = elliptic.P521()
+ default:
+ return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
+ }
+
+ X, Y := elliptic.Unmarshal(curve, key.Pub)
+ if X == nil || Y == nil {
+ return nil, errors.New("ssh: failed to unmarshal public key")
+ }
+
+ if key.D.Cmp(curve.Params().N) >= 0 {
+ return nil, errors.New("ssh: scalar is out of range")
+ }
+
+ x, y := curve.ScalarBaseMult(key.D.Bytes())
+ if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
+ return nil, errors.New("ssh: public key does not match private key")
+ }
+
+ return &ecdsa.PrivateKey{
+ PublicKey: ecdsa.PublicKey{
+ Curve: curve,
+ X: X,
+ Y: Y,
+ },
+ D: key.D,
+ }, nil
default:
return nil, errors.New("ssh: unhandled key type")
}
}
+func checkOpenSSHKeyPadding(pad []byte) error {
+ for i, b := range pad {
+ if int(b) != i+1 {
+ return errors.New("ssh: padding not as expected")
+ }
+ }
+ return nil
+}
+
// FingerprintLegacyMD5 returns the user presentation of the key's
// fingerprint as described by RFC 4716 section 4.
func FingerprintLegacyMD5(pubKey PublicKey) string {
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 7a5a1d7ad..7d42a8c88 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -284,8 +284,8 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
func isAcceptableAlgo(algo string) bool {
switch algo {
- case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
- CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
+ case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
return true
}
return false
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
index 2f04ee5b5..d1b4fca3a 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go
@@ -7,6 +7,7 @@ package terminal
import (
"bytes"
"io"
+ "runtime"
"strconv"
"sync"
"unicode/utf8"
@@ -939,6 +940,8 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
// readPasswordLine reads from reader until it finds \n or io.EOF.
// The slice returned does not include the \n.
// readPasswordLine also ignores any \r it finds.
+// Windows uses \r as end of line. So, on Windows, readPasswordLine
+// reads until it finds \r and ignores any \n it finds during processing.
func readPasswordLine(reader io.Reader) ([]byte, error) {
var buf [1]byte
var ret []byte
@@ -947,10 +950,20 @@ func readPasswordLine(reader io.Reader) ([]byte, error) {
n, err := reader.Read(buf[:])
if n > 0 {
switch buf[0] {
+ case '\b':
+ if len(ret) > 0 {
+ ret = ret[:len(ret)-1]
+ }
case '\n':
- return ret, nil
+ if runtime.GOOS != "windows" {
+ return ret, nil
+ }
+ // otherwise ignore \n
case '\r':
- // remove \r from passwords on Windows
+ if runtime.GOOS == "windows" {
+ return ret, nil
+ }
+ // otherwise ignore \r
default:
ret = append(ret, buf[0])
}
diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
index 5cfdf8f3f..f614e9cb6 100644
--- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
+++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
@@ -85,8 +85,8 @@ func ReadPassword(fd int) ([]byte, error) {
}
old := st
- st &^= (windows.ENABLE_ECHO_INPUT)
- st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
+ st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT)
+ st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
return nil, err
}
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
index 291df5c83..428283f0b 100644
--- a/vendor/golang.org/x/oauth2/oauth2.go
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -117,7 +117,7 @@ var (
// ApprovalForce forces the users to view the consent dialog
// and confirm the permissions request at the URL returned
// from AuthCodeURL, even if they've already done so.
- ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent")
+ ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
)
// An AuthCodeOption is passed to Config.AuthCodeURL.
diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go
index 85c18b5a3..ae93e2471 100644
--- a/vendor/golang.org/x/time/rate/rate.go
+++ b/vendor/golang.org/x/time/rate/rate.go
@@ -281,23 +281,6 @@ func (lim *Limiter) SetLimitAt(now time.Time, newLimit Limit) {
lim.limit = newLimit
}
-// SetBurst is shorthand for SetBurstAt(time.Now(), newBurst).
-func (lim *Limiter) SetBurst(newBurst int) {
- lim.SetBurstAt(time.Now(), newBurst)
-}
-
-// SetBurstAt sets a new burst size for the limiter.
-func (lim *Limiter) SetBurstAt(now time.Time, newBurst int) {
- lim.mu.Lock()
- defer lim.mu.Unlock()
-
- now, _, tokens := lim.advance(now)
-
- lim.last = now
- lim.tokens = tokens
- lim.burst = newBurst
-}
-
// reserveN is a helper method for AllowN, ReserveN, and WaitN.
// maxFutureReserve specifies the maximum reservation wait duration allowed.
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
diff --git a/vendor/golang.org/x/xerrors/doc.go b/vendor/golang.org/x/xerrors/doc.go
index 1ad48f50b..eef99d9d5 100644
--- a/vendor/golang.org/x/xerrors/doc.go
+++ b/vendor/golang.org/x/xerrors/doc.go
@@ -4,22 +4,19 @@
// Package xerrors implements functions to manipulate errors.
//
-// This package supports transitioning to the Go 2 proposal for error values:
+// This package is based on the Go 2 proposal for error values:
// https://golang.org/design/29934-error-values
//
-// Most of the functions and types in this package will be incorporated into the
-// standard library's errors package in Go 1.13; the behavior of this package's
-// Errorf function will be incorporated into the standard library's fmt.Errorf.
-// Use this package to get equivalent behavior in all supported Go versions. For
-// example, create errors using
+// These functions were incorporated into the standard library's errors package
+// in Go 1.13:
+// - Is
+// - As
+// - Unwrap
//
-// xerrors.New("write failed")
+// Also, Errorf's %w verb was incorporated into fmt.Errorf.
//
-// or
+// Use this package to get equivalent behavior in all supported Go versions.
//
-// xerrors.Errorf("while reading: %v", err)
-//
-// If you want your error type to participate in the new formatting
-// implementation for %v and %+v, provide it with a Format method that calls
-// xerrors.FormatError, as shown in the example for FormatError.
+// No other features of this package were included in Go 1.13, and at present
+// there are no plans to include any of them.
package xerrors // import "golang.org/x/xerrors"
diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go
index 74c1c93ec..829862ddf 100644
--- a/vendor/golang.org/x/xerrors/fmt.go
+++ b/vendor/golang.org/x/xerrors/fmt.go
@@ -7,10 +7,14 @@ package xerrors
import (
"fmt"
"strings"
+ "unicode"
+ "unicode/utf8"
"golang.org/x/xerrors/internal"
)
+const percentBangString = "%!"
+
// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
@@ -18,29 +22,71 @@ import (
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
-// format string ends with ": %w", the returned error implements Wrapper
-// with an Unwrap method returning it.
+// format string ends with ": %w", the returned error implements an Unwrap
+// method returning it.
+//
+// If the format specifier includes a %w verb with an error operand in a
+// position other than at the end, the returned error will still implement an
+// Unwrap method returning the operand, but the error's Format method will not
+// return the wrapped error.
+//
+// It is invalid to include more than one %w verb or to supply it with an
+// operand that does not implement the error interface. The %w verb is otherwise
+// a synonym for %v.
func Errorf(format string, a ...interface{}) error {
- err, wrap := lastError(format, a)
format = formatPlusW(format)
- if err == nil {
- return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
+ wrap := strings.HasSuffix(format, ": %w")
+ idx, format2, ok := parsePercentW(format)
+ percentWElsewhere := !wrap && idx >= 0
+ if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
+ err := errorAt(a, len(a)-1)
+ if err == nil {
+ return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ }
+ // TODO: this is not entirely correct. The error value could be
+ // printed elsewhere in format if it mixes numbered with unnumbered
+ // substitutions. With relatively small changes to doPrintf we can
+ // have it optionally ignore extra arguments and pass the argument
+ // list in its entirety.
+ msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
+ frame := Frame{}
+ if internal.EnableTrace {
+ frame = Caller(1)
+ }
+ if wrap {
+ return &wrapError{msg, err, frame}
+ }
+ return &noWrapError{msg, err, frame}
+ }
+ // Support %w anywhere.
+ // TODO: don't repeat the wrapped error's message when %w occurs in the middle.
+ msg := fmt.Sprintf(format2, a...)
+ if idx < 0 {
+ return &noWrapError{msg, nil, Caller(1)}
+ }
+ err := errorAt(a, idx)
+ if !ok || err == nil {
+ // Too many %ws or argument of %w is not an error. Approximate the Go
+ // 1.13 fmt.Errorf message.
+ return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
}
-
- // TODO: this is not entirely correct. The error value could be
- // printed elsewhere in format if it mixes numbered with unnumbered
- // substitutions. With relatively small changes to doPrintf we can
- // have it optionally ignore extra arguments and pass the argument
- // list in its entirety.
- msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
frame := Frame{}
if internal.EnableTrace {
frame = Caller(1)
}
- if wrap {
- return &wrapError{msg, err, frame}
+ return &wrapError{msg, err, frame}
+}
+
+func errorAt(args []interface{}, i int) error {
+ if i < 0 || i >= len(args) {
+ return nil
}
- return &noWrapError{msg, err, frame}
+ err, ok := args[i].(error)
+ if !ok {
+ return nil
+ }
+ return err
}
// formatPlusW is used to avoid the vet check that will barf at %w.
@@ -48,24 +94,56 @@ func formatPlusW(s string) string {
return s
}
-func lastError(format string, a []interface{}) (err error, wrap bool) {
- wrap = strings.HasSuffix(format, ": %w")
- if !wrap &&
- !strings.HasSuffix(format, ": %s") &&
- !strings.HasSuffix(format, ": %v") {
- return nil, false
- }
-
- if len(a) == 0 {
- return nil, false
+// Return the index of the only %w in format, or -1 if none.
+// Also return a rewritten format string with %w replaced by %v, and
+// false if there is more than one %w.
+// TODO: handle "%[N]w".
+func parsePercentW(format string) (idx int, newFormat string, ok bool) {
+ // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
+ idx = -1
+ ok = true
+ n := 0
+ sz := 0
+ var isW bool
+ for i := 0; i < len(format); i += sz {
+ if format[i] != '%' {
+ sz = 1
+ continue
+ }
+ // "%%" is not a format directive.
+ if i+1 < len(format) && format[i+1] == '%' {
+ sz = 2
+ continue
+ }
+ sz, isW = parsePrintfVerb(format[i:])
+ if isW {
+ if idx >= 0 {
+ ok = false
+ } else {
+ idx = n
+ }
+ // "Replace" the last character, the 'w', with a 'v'.
+ p := i + sz - 1
+ format = format[:p] + "v" + format[p+1:]
+ }
+ n++
}
+ return idx, format, ok
+}
- err, ok := a[len(a)-1].(error)
- if !ok {
- return nil, false
+// Parse the printf verb starting with a % at s[0].
+// Return how many bytes it occupies and whether the verb is 'w'.
+func parsePrintfVerb(s string) (int, bool) {
+ // Assume only that the directive is a sequence of non-letters followed by a single letter.
+ sz := 0
+ var r rune
+ for i := 1; i < len(s); i += sz {
+ r, sz = utf8.DecodeRuneInString(s[i:])
+ if unicode.IsLetter(r) {
+ return i + sz, r == 'w'
+ }
}
-
- return err, wrap
+ return len(s), false
}
type noWrapError struct {
diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
index 0b9907f89..57ae35f6b 100644
--- a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
+++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
@@ -1,15 +1,12 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/rpc/status.proto
-package status
+package status // import "google.golang.org/genproto/googleapis/rpc/status"
-import (
- fmt "fmt"
- math "math"
-
- proto "github.com/golang/protobuf/proto"
- any "github.com/golang/protobuf/ptypes/any"
-)
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import any "github.com/golang/protobuf/ptypes/any"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@@ -20,7 +17,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs. It is
@@ -96,17 +93,16 @@ func (m *Status) Reset() { *m = Status{} }
func (m *Status) String() string { return proto.CompactTextString(m) }
func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) {
- return fileDescriptor_24d244abaf643bfe, []int{0}
+ return fileDescriptor_status_ced6ddf76350620b, []int{0}
}
-
func (m *Status) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Status.Unmarshal(m, b)
}
func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Status.Marshal(b, m, deterministic)
}
-func (m *Status) XXX_Merge(src proto.Message) {
- xxx_messageInfo_Status.Merge(m, src)
+func (dst *Status) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Status.Merge(dst, src)
}
func (m *Status) XXX_Size() int {
return xxx_messageInfo_Status.Size(m)
@@ -142,9 +138,9 @@ func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status")
}
-func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) }
+func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_status_ced6ddf76350620b) }
-var fileDescriptor_24d244abaf643bfe = []byte{
+var fileDescriptor_status_ced6ddf76350620b = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 814ea264e..564717381 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -33,7 +33,7 @@ github.com/VividCortex/ewma
github.com/acarl005/stripansi
# github.com/beorn7/perks v1.0.1
github.com/beorn7/perks/quantile
-# github.com/blang/semver v3.5.1+incompatible
+# github.com/blang/semver v3.1.0+incompatible
github.com/blang/semver
# github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
github.com/buger/goterm
@@ -62,7 +62,7 @@ github.com/containernetworking/plugins/pkg/ns
github.com/containernetworking/plugins/pkg/utils/hwaddr
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
-# github.com/containers/buildah v1.13.1
+# github.com/containers/buildah v1.14.1-0.20200227103754-f0c3fd7c3d34
github.com/containers/buildah
github.com/containers/buildah/bind
github.com/containers/buildah/chroot
@@ -77,8 +77,9 @@ github.com/containers/buildah/pkg/parse
github.com/containers/buildah/pkg/secrets
github.com/containers/buildah/pkg/umask
github.com/containers/buildah/util
-# github.com/containers/common v0.0.7
-github.com/containers/common/pkg/cgroups
+# github.com/containers/common v0.4.2
+github.com/containers/common/pkg/capabilities
+github.com/containers/common/pkg/config
github.com/containers/common/pkg/unshare
# github.com/containers/conmon v2.0.10+incompatible
github.com/containers/conmon/runner/config
@@ -141,7 +142,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.15.8
+# github.com/containers/storage v1.16.0
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -257,14 +258,14 @@ github.com/docker/go-units
github.com/docker/libnetwork/resolvconf
github.com/docker/libnetwork/resolvconf/dns
github.com/docker/libnetwork/types
-# github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c
+# github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/docker/spdystream
github.com/docker/spdystream/spdy
# github.com/etcd-io/bbolt v1.3.3
github.com/etcd-io/bbolt
# github.com/fsnotify/fsnotify v1.4.7
github.com/fsnotify/fsnotify
-# github.com/fsouza/go-dockerclient v1.6.0
+# github.com/fsouza/go-dockerclient v1.6.3
github.com/fsouza/go-dockerclient
# github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
github.com/fullsailor/pkcs7
@@ -309,11 +310,11 @@ github.com/hpcloud/tail/winfile
github.com/imdario/mergo
# github.com/inconshreveable/mousetrap v1.0.0
github.com/inconshreveable/mousetrap
-# github.com/ishidawataru/sctp v0.0.0-20180918013207-6e2cb1366111
+# github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07
github.com/ishidawataru/sctp
# github.com/json-iterator/go v1.1.9
github.com/json-iterator/go
-# github.com/klauspost/compress v1.9.8
+# github.com/klauspost/compress v1.10.0
github.com/klauspost/compress/flate
github.com/klauspost/compress/fse
github.com/klauspost/compress/huff0
@@ -324,7 +325,7 @@ github.com/klauspost/compress/zstd/internal/xxhash
github.com/klauspost/pgzip
# github.com/konsorten/go-windows-terminal-sequences v1.0.2
github.com/konsorten/go-windows-terminal-sequences
-# github.com/mattn/go-shellwords v1.0.9
+# github.com/mattn/go-shellwords v1.0.10
github.com/mattn/go-shellwords
# github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/matttproud/golang_protobuf_extensions/pbutil
@@ -334,7 +335,7 @@ github.com/mistifyio/go-zfs
github.com/modern-go/concurrent
# github.com/modern-go/reflect2 v1.0.1
github.com/modern-go/reflect2
-# github.com/morikuni/aec v1.0.0
+# github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
github.com/morikuni/aec
# github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
github.com/mrunalp/fileutils
@@ -404,7 +405,7 @@ github.com/opencontainers/runtime-tools/generate
github.com/opencontainers/runtime-tools/generate/seccomp
github.com/opencontainers/runtime-tools/specerror
github.com/opencontainers/runtime-tools/validate
-# github.com/opencontainers/selinux v1.3.1
+# github.com/opencontainers/selinux v1.3.2
github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label
# github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316
@@ -466,11 +467,11 @@ github.com/seccomp/libseccomp-golang
# github.com/sirupsen/logrus v1.4.2
github.com/sirupsen/logrus
github.com/sirupsen/logrus/hooks/syslog
-# github.com/spf13/cobra v0.0.5
+# github.com/spf13/cobra v0.0.6
github.com/spf13/cobra
# github.com/spf13/pflag v1.0.5
github.com/spf13/pflag
-# github.com/stretchr/testify v1.4.0
+# github.com/stretchr/testify v1.5.1
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
@@ -496,7 +497,7 @@ github.com/uber/jaeger-client-go/thrift-gen/sampling
github.com/uber/jaeger-client-go/thrift-gen/zipkincore
github.com/uber/jaeger-client-go/transport
github.com/uber/jaeger-client-go/utils
-# github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5
+# github.com/uber/jaeger-lib v2.2.0+incompatible
github.com/uber/jaeger-lib/metrics
# github.com/ulikunitz/xz v0.5.6
github.com/ulikunitz/xz
@@ -525,7 +526,7 @@ github.com/vishvananda/netns
github.com/xeipuuv/gojsonpointer
# github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415
github.com/xeipuuv/gojsonreference
-# github.com/xeipuuv/gojsonschema v1.1.0
+# github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66
github.com/xeipuuv/gojsonschema
# go.opencensus.io v0.22.0
go.opencensus.io
@@ -535,7 +536,8 @@ go.opencensus.io/trace/internal
go.opencensus.io/trace/tracestate
# go.uber.org/atomic v1.4.0
go.uber.org/atomic
-# golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
+# golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
+golang.org/x/crypto/blowfish
golang.org/x/crypto/cast5
golang.org/x/crypto/chacha20
golang.org/x/crypto/curve25519
@@ -551,6 +553,7 @@ golang.org/x/crypto/openpgp/s2k
golang.org/x/crypto/pbkdf2
golang.org/x/crypto/poly1305
golang.org/x/crypto/ssh
+golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/terminal
# golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
golang.org/x/net/context
@@ -564,7 +567,7 @@ golang.org/x/net/http2/hpack
golang.org/x/net/idna
golang.org/x/net/internal/socks
golang.org/x/net/proxy
-# golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
+# golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
golang.org/x/oauth2
golang.org/x/oauth2/internal
# golang.org/x/sync v0.0.0-20190423024810-112230192c58
@@ -595,12 +598,12 @@ golang.org/x/text/secure/bidirule
golang.org/x/text/transform
golang.org/x/text/unicode/bidi
golang.org/x/text/unicode/norm
-# golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0
+# golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
golang.org/x/time/rate
-# golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
+# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
golang.org/x/xerrors
golang.org/x/xerrors/internal
-# google.golang.org/appengine v1.6.1
+# google.golang.org/appengine v1.5.0
google.golang.org/appengine/internal
google.golang.org/appengine/internal/base
google.golang.org/appengine/internal/datastore
@@ -608,7 +611,7 @@ google.golang.org/appengine/internal/log
google.golang.org/appengine/internal/remote_api
google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch
-# google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601
+# google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb
google.golang.org/genproto/googleapis/rpc/status
# google.golang.org/grpc v1.24.0
google.golang.org/grpc/codes
@@ -689,7 +692,7 @@ k8s.io/client-go/util/homedir
k8s.io/client-go/util/keyutil
# k8s.io/klog v1.0.0
k8s.io/klog
-# k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a
+# k8s.io/utils v0.0.0-20190221042446-c2654d5206da
k8s.io/utils/integer
# sigs.k8s.io/yaml v1.1.0
sigs.k8s.io/yaml