aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml123
-rw-r--r--.copr/Makefile21
-rw-r--r--.copr/prepare.sh39
-rwxr-xr-x.github/actions/check_cirrus_cron/cron_failures.sh6
-rw-r--r--.github/issue-labeler.yml13
-rw-r--r--.github/workflows/check_cirrus_cron.yml24
-rw-r--r--.github/workflows/issue-labeler.yml15
-rw-r--r--Makefile64
-rw-r--r--RELEASE_NOTES.md258
-rw-r--r--SECURITY.md4
-rw-r--r--build_osx.md2
-rw-r--r--cmd/podman/common/netflags.go102
-rw-r--r--cmd/podman/generate/systemd.go12
-rw-r--r--cmd/podman/images/build.go15
-rw-r--r--cmd/podman/images/scp.go30
-rw-r--r--cmd/podman/images/scp_utils.go3
-rw-r--r--cmd/podman/machine/start.go2
-rw-r--r--cmd/podman/networks/create.go64
-rw-r--r--cmd/podman/networks/list.go1
-rw-r--r--cmd/podman/pods/create.go2
-rw-r--r--cmd/podman/registry/config.go15
-rw-r--r--cmd/podman/root.go18
-rw-r--r--cmd/podman/system/reset.go6
-rwxr-xr-xcontrib/build_rpm.sh83
-rw-r--r--contrib/cirrus/cron-fail_addrs.csv1
-rw-r--r--contrib/cirrus/lib.sh42
-rwxr-xr-xcontrib/cirrus/logcollector.sh13
-rwxr-xr-xcontrib/cirrus/logformatter2
-rwxr-xr-xcontrib/cirrus/logformatter.t16
-rwxr-xr-xcontrib/cirrus/runner.sh5
-rwxr-xr-xcontrib/cirrus/setup_environment.sh66
-rw-r--r--contrib/helloimage/Containerfile8
-rw-r--r--contrib/helloimage/README.md55
-rwxr-xr-xcontrib/helloimage/podman_hello_world.bash23
-rw-r--r--contrib/msi/podman.wxs4
-rw-r--r--contrib/spec/podman.spec.in571
-rw-r--r--docs/source/markdown/podman-attach.1.md4
-rw-r--r--docs/source/markdown/podman-build.1.md69
-rw-r--r--docs/source/markdown/podman-container-checkpoint.1.md2
-rw-r--r--docs/source/markdown/podman-container-cleanup.1.md2
-rw-r--r--docs/source/markdown/podman-container-diff.1.md2
-rw-r--r--docs/source/markdown/podman-container-exists.1.md6
-rw-r--r--docs/source/markdown/podman-container-inspect.1.md2
-rw-r--r--docs/source/markdown/podman-container-prune.1.md8
-rw-r--r--docs/source/markdown/podman-container-restore.1.md4
-rw-r--r--docs/source/markdown/podman-container-runlabel.1.md2
-rw-r--r--docs/source/markdown/podman-create.1.md38
-rw-r--r--docs/source/markdown/podman-diff.1.md2
-rw-r--r--docs/source/markdown/podman-exec.1.md2
-rw-r--r--docs/source/markdown/podman-generate-kube.1.md2
-rw-r--r--docs/source/markdown/podman-generate-systemd.1.md18
-rw-r--r--docs/source/markdown/podman-image-prune.1.md13
-rw-r--r--docs/source/markdown/podman-image-scp.1.md2
-rw-r--r--docs/source/markdown/podman-image-sign.1.md4
-rw-r--r--docs/source/markdown/podman-image-trust.1.md2
-rw-r--r--docs/source/markdown/podman-images.1.md33
-rw-r--r--docs/source/markdown/podman-init.1.md2
-rw-r--r--docs/source/markdown/podman-inspect.1.md2
-rw-r--r--docs/source/markdown/podman-kill.1.md2
-rw-r--r--docs/source/markdown/podman-load.1.md2
-rw-r--r--docs/source/markdown/podman-login.1.md2
-rw-r--r--docs/source/markdown/podman-logs.1.md4
-rw-r--r--docs/source/markdown/podman-machine-list.1.md4
-rw-r--r--docs/source/markdown/podman-manifest-add.1.md2
-rw-r--r--docs/source/markdown/podman-manifest-push.1.md10
-rw-r--r--docs/source/markdown/podman-mount.1.md4
-rw-r--r--docs/source/markdown/podman-network-create.1.md20
-rw-r--r--docs/source/markdown/podman-network-exists.1.md2
-rw-r--r--docs/source/markdown/podman-network-prune.1.md21
-rw-r--r--docs/source/markdown/podman-network-reload.1.md2
-rw-r--r--docs/source/markdown/podman-play-kube.1.md10
-rw-r--r--docs/source/markdown/podman-pod-create.1.md6
-rw-r--r--docs/source/markdown/podman-pod-inspect.1.md2
-rw-r--r--docs/source/markdown/podman-pod-kill.1.md2
-rw-r--r--docs/source/markdown/podman-pod-logs.1.md4
-rw-r--r--docs/source/markdown/podman-pod-pause.1.md2
-rw-r--r--docs/source/markdown/podman-pod-ps.1.md2
-rw-r--r--docs/source/markdown/podman-pod-restart.1.md2
-rw-r--r--docs/source/markdown/podman-pod-rm.1.md2
-rw-r--r--docs/source/markdown/podman-pod-start.1.md2
-rw-r--r--docs/source/markdown/podman-pod-stats.1.md2
-rw-r--r--docs/source/markdown/podman-pod-stop.1.md2
-rw-r--r--docs/source/markdown/podman-pod-top.1.md2
-rw-r--r--docs/source/markdown/podman-pod-unpause.1.md2
-rw-r--r--docs/source/markdown/podman-port.1.md2
-rw-r--r--docs/source/markdown/podman-ps.1.md2
-rw-r--r--docs/source/markdown/podman-pull.1.md4
-rw-r--r--docs/source/markdown/podman-push.1.md10
-rw-r--r--docs/source/markdown/podman-remote.1.md26
-rw-r--r--docs/source/markdown/podman-restart.1.md2
-rw-r--r--docs/source/markdown/podman-rm.1.md2
-rw-r--r--docs/source/markdown/podman-run.1.md40
-rw-r--r--docs/source/markdown/podman-start.1.md2
-rw-r--r--docs/source/markdown/podman-stats.1.md8
-rw-r--r--docs/source/markdown/podman-stop.1.md2
-rw-r--r--docs/source/markdown/podman-system-prune.1.md12
-rw-r--r--docs/source/markdown/podman-system-reset.1.md13
-rw-r--r--docs/source/markdown/podman-top.1.md2
-rw-r--r--docs/source/markdown/podman-unmount.1.md2
-rw-r--r--docs/source/markdown/podman-untag.1.md2
-rw-r--r--docs/source/markdown/podman-volume-exists.1.md2
-rw-r--r--docs/source/markdown/podman-volume-prune.1.md18
-rw-r--r--docs/source/markdown/podman-wait.1.md2
-rw-r--r--docs/source/markdown/podman.1.md45
-rw-r--r--go.mod36
-rw-r--r--go.sum154
-rwxr-xr-xhack/bats19
-rwxr-xr-xhack/get_ci_vm.sh7
-rwxr-xr-xhack/podman-socat2
-rw-r--r--libpod/container_exec.go40
-rw-r--r--libpod/container_inspect.go2
-rw-r--r--libpod/container_internal_linux.go42
-rw-r--r--libpod/networking_linux.go44
-rw-r--r--libpod/oci_attach_linux.go2
-rw-r--r--libpod/oci_conmon_exec_linux.go1
-rw-r--r--libpod/oci_conmon_linux.go6
-rw-r--r--libpod/reset.go17
-rw-r--r--libpod/runtime_ctr.go50
-rw-r--r--libpod/util.go13
-rw-r--r--pkg/api/handlers/compat/auth.go2
-rw-r--r--pkg/api/handlers/compat/changes.go4
-rw-r--r--pkg/api/handlers/compat/containers.go22
-rw-r--r--pkg/api/handlers/compat/containers_archive.go24
-rw-r--r--pkg/api/handlers/compat/containers_attach.go8
-rw-r--r--pkg/api/handlers/compat/containers_create.go23
-rw-r--r--pkg/api/handlers/compat/containers_export.go8
-rw-r--r--pkg/api/handlers/compat/containers_logs.go4
-rw-r--r--pkg/api/handlers/compat/containers_prune.go2
-rw-r--r--pkg/api/handlers/compat/containers_restart.go3
-rw-r--r--pkg/api/handlers/compat/containers_stats.go6
-rw-r--r--pkg/api/handlers/compat/containers_stop.go3
-rw-r--r--pkg/api/handlers/compat/containers_top.go6
-rw-r--r--pkg/api/handlers/compat/events.go4
-rw-r--r--pkg/api/handlers/compat/exec.go14
-rw-r--r--pkg/api/handlers/compat/images.go94
-rw-r--r--pkg/api/handlers/compat/images_build.go40
-rw-r--r--pkg/api/handlers/compat/images_history.go2
-rw-r--r--pkg/api/handlers/compat/images_prune.go2
-rw-r--r--pkg/api/handlers/compat/images_push.go13
-rw-r--r--pkg/api/handlers/compat/images_remove.go6
-rw-r--r--pkg/api/handlers/compat/images_search.go6
-rw-r--r--pkg/api/handlers/compat/images_tag.go8
-rw-r--r--pkg/api/handlers/compat/info.go40
-rw-r--r--pkg/api/handlers/compat/networks.go42
-rw-r--r--pkg/api/handlers/compat/resize.go8
-rw-r--r--pkg/api/handlers/compat/secrets.go13
-rw-r--r--pkg/api/handlers/compat/version.go4
-rw-r--r--pkg/api/handlers/compat/volumes.go16
-rw-r--r--pkg/api/handlers/libpod/containers.go20
-rw-r--r--pkg/api/handlers/libpod/containers_create.go2
-rw-r--r--pkg/api/handlers/libpod/containers_stats.go4
-rw-r--r--pkg/api/handlers/libpod/generate.go38
-rw-r--r--pkg/api/handlers/libpod/healthcheck.go4
-rw-r--r--pkg/api/handlers/libpod/images.go104
-rw-r--r--pkg/api/handlers/libpod/images_pull.go9
-rw-r--r--pkg/api/handlers/libpod/manifests.go49
-rw-r--r--pkg/api/handlers/libpod/networks.go26
-rw-r--r--pkg/api/handlers/libpod/play.go27
-rw-r--r--pkg/api/handlers/libpod/pods.go65
-rw-r--r--pkg/api/handlers/libpod/secrets.go3
-rw-r--r--pkg/api/handlers/libpod/system.go4
-rw-r--r--pkg/api/handlers/libpod/volumes.go14
-rw-r--r--pkg/api/handlers/utils/containers.go4
-rw-r--r--pkg/api/handlers/utils/errors.go35
-rw-r--r--pkg/api/server/register_generate.go21
-rw-r--r--pkg/api/server/register_swarm.go2
-rw-r--r--pkg/api/server/swagger.go3
-rw-r--r--pkg/auth/auth_test.go2
-rw-r--r--pkg/bindings/generate/types.go6
-rw-r--r--pkg/bindings/generate/types_systemd_options.go45
-rw-r--r--pkg/bindings/images/build.go4
-rw-r--r--pkg/bindings/test/common_test.go2
-rw-r--r--pkg/bindings/test/containers_test.go2
-rw-r--r--pkg/domain/entities/generate.go6
-rw-r--r--pkg/domain/entities/network.go6
-rw-r--r--pkg/domain/infra/abi/images.go73
-rw-r--r--pkg/domain/infra/abi/images_test.go17
-rw-r--r--pkg/domain/infra/abi/play.go10
-rw-r--r--pkg/domain/infra/runtime_libpod.go2
-rw-r--r--pkg/domain/infra/tunnel/generate.go12
-rw-r--r--pkg/env/env_unix.go (renamed from pkg/env/env_supported.go)2
-rw-r--r--pkg/env/env_unsupported.go8
-rw-r--r--pkg/env/env_windows.go25
-rw-r--r--pkg/machine/ignition.go23
-rw-r--r--pkg/machine/qemu/machine.go4
-rw-r--r--pkg/machine/wsl/machine.go165
-rw-r--r--pkg/machine/wsl/util_windows.go19
-rw-r--r--pkg/rootless/rootless_linux.go4
-rw-r--r--pkg/specgen/generate/config_linux.go11
-rw-r--r--pkg/specgen/generate/kube/kube.go130
-rw-r--r--pkg/specgen/generate/kube/play_test.go398
-rw-r--r--pkg/specgen/generate/kube/volume.go2
-rw-r--r--pkg/specgen/generate/pod_create.go6
-rw-r--r--pkg/specgen/generate/security.go2
-rw-r--r--pkg/specgen/namespaces.go4
-rw-r--r--pkg/specgen/podspecgen.go2
-rw-r--r--pkg/specgen/specgen.go4
-rw-r--r--pkg/specgenutil/specgen.go10
-rw-r--r--pkg/specgenutil/util.go2
-rw-r--r--pkg/systemd/generate/containers.go23
-rw-r--r--pkg/systemd/generate/containers_test.go188
-rw-r--r--pkg/systemd/generate/pods.go20
-rw-r--r--pkg/systemd/generate/pods_test.go203
-rw-r--r--pkg/util/mountOpts.go18
-rw-r--r--podman.spec.rpkg19
-rw-r--r--test/apiv2/10-images.at8
-rw-r--r--test/apiv2/20-containers.at47
-rw-r--r--test/apiv2/python/rest_api/fixtures/podman.py2
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py2
-rwxr-xr-xtest/apiv2/test-apiv211
-rwxr-xr-xtest/compose/test-compose4
-rw-r--r--test/e2e/build_test.go28
-rw-r--r--test/e2e/common_test.go137
-rw-r--r--test/e2e/containers_conf_test.go231
-rw-r--r--test/e2e/create_staticip_test.go6
-rw-r--r--test/e2e/create_staticmac_test.go2
-rw-r--r--test/e2e/create_test.go2
-rw-r--r--test/e2e/generate_systemd_test.go92
-rw-r--r--test/e2e/libpod_suite_remote_test.go5
-rw-r--r--test/e2e/login_logout_test.go4
-rw-r--r--test/e2e/network_connect_disconnect_test.go34
-rw-r--r--test/e2e/network_create_test.go109
-rw-r--r--test/e2e/network_test.go82
-rw-r--r--test/e2e/play_build_test.go4
-rw-r--r--test/e2e/play_kube_test.go37
-rw-r--r--test/e2e/pod_create_test.go14
-rw-r--r--test/e2e/pod_ps_test.go6
-rw-r--r--test/e2e/ps_test.go6
-rw-r--r--test/e2e/run_networking_test.go84
-rw-r--r--test/e2e/run_staticip_test.go2
-rw-r--r--test/e2e/run_test.go10
-rw-r--r--test/e2e/run_volume_test.go54
-rw-r--r--test/e2e/search_test.go93
-rw-r--r--test/e2e/stats_test.go13
-rw-r--r--test/e2e/system_reset_test.go18
-rw-r--r--test/e2e/volume_create_test.go2
-rw-r--r--test/python/docker/__init__.py23
-rw-r--r--test/python/docker/compat/test_system.py5
-rw-r--r--test/system/005-info.bats13
-rw-r--r--test/system/030-run.bats14
-rw-r--r--test/system/120-load.bats80
-rw-r--r--test/system/160-volumes.bats4
-rw-r--r--test/system/200-pod.bats11
-rw-r--r--test/system/255-auto-update.bats6
-rw-r--r--test/system/272-system-connection.bats8
-rw-r--r--test/system/410-selinux.bats3
-rw-r--r--test/system/500-networking.bats31
-rw-r--r--test/system/README.md1
-rw-r--r--test/system/helpers.bash9
-rw-r--r--test/utils/utils.go39
-rw-r--r--troubleshooting.md14
-rw-r--r--utils/utils.go15
-rw-r--r--vendor/github.com/Microsoft/hcsshim/.golangci.yml3
-rw-r--r--vendor/github.com/Microsoft/hcsshim/go.mod2
-rw-r--r--vendor/github.com/Microsoft/hcsshim/go.sum3
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go16
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go56
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/winapi/console.go44
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go10
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go2
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go46
-rw-r--r--vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go9
-rw-r--r--vendor/github.com/buger/goterm/.gitignore1
-rw-r--r--vendor/github.com/buger/goterm/box.go66
-rw-r--r--vendor/github.com/buger/goterm/go.mod5
-rw-r--r--vendor/github.com/buger/goterm/go.sum2
-rw-r--r--vendor/github.com/buger/goterm/plot.go3
-rw-r--r--vendor/github.com/buger/goterm/terminal.go10
-rw-r--r--vendor/github.com/buger/goterm/terminal_nosysioctl.go2
-rw-r--r--vendor/github.com/buger/goterm/terminal_sysioctl.go1
-rw-r--r--vendor/github.com/buger/goterm/terminal_windows.go23
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go2
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod2
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum4
-rw-r--r--vendor/github.com/containers/buildah/.cirrus.yml62
-rw-r--r--vendor/github.com/containers/buildah/.gitignore4
-rw-r--r--vendor/github.com/containers/buildah/.golangci.yml19
-rw-r--r--vendor/github.com/containers/buildah/CHANGELOG.md172
-rw-r--r--vendor/github.com/containers/buildah/Makefile1
-rw-r--r--vendor/github.com/containers/buildah/bind/mount.go2
-rw-r--r--vendor/github.com/containers/buildah/changelog.txt170
-rw-r--r--vendor/github.com/containers/buildah/chroot/run.go17
-rw-r--r--vendor/github.com/containers/buildah/define/types.go2
-rw-r--r--vendor/github.com/containers/buildah/go.mod17
-rw-r--r--vendor/github.com/containers/buildah/go.sum123
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go13
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/executor.go19
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/stage_executor.go19
-rw-r--r--vendor/github.com/containers/buildah/internal/parse/parse.go2
-rw-r--r--vendor/github.com/containers/buildah/pkg/cli/common.go14
-rw-r--r--vendor/github.com/containers/buildah/pkg/overlay/overlay.go134
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse.go80
-rw-r--r--vendor/github.com/containers/buildah/run_linux.go48
-rw-r--r--vendor/github.com/containers/buildah/util.go4
-rw-r--r--vendor/github.com/containers/buildah/util/util.go47
-rw-r--r--vendor/github.com/containers/common/libnetwork/cni/config.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/netavark/config.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/netavark/exec.go2
-rw-r--r--vendor/github.com/containers/common/libnetwork/netavark/network.go16
-rw-r--r--vendor/github.com/containers/common/libnetwork/netavark/run.go5
-rw-r--r--vendor/github.com/containers/common/libnetwork/network/interface.go14
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go20
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf18
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go41
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_linux.go6
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_unsupported.go6
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_windows.go6
-rw-r--r--vendor/github.com/containers/common/pkg/flag/flag.go2
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse.go20
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go2
-rw-r--r--vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go33
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/github.com/containers/image/v5/copy/copy.go5
-rw-r--r--vendor/github.com/containers/image/v5/copy/sign.go4
-rw-r--r--vendor/github.com/containers/image/v5/manifest/common.go4
-rw-r--r--vendor/github.com/containers/image/v5/pkg/docker/config/config.go4
-rw-r--r--vendor/github.com/containers/image/v5/sif/load.go211
-rw-r--r--vendor/github.com/containers/image/v5/sif/src.go217
-rw-r--r--vendor/github.com/containers/image/v5/sif/transport.go164
-rw-r--r--vendor/github.com/containers/image/v5/signature/docker.go30
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism.go11
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go37
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go12
-rw-r--r--vendor/github.com/containers/image/v5/signature/signature.go10
-rw-r--r--vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go2
-rw-r--r--vendor/github.com/containers/image/v5/version/version.go4
-rw-r--r--vendor/github.com/containers/psgo/go.mod5
-rw-r--r--vendor/github.com/containers/psgo/go.sum972
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/ns.go16
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go102
-rw-r--r--vendor/github.com/containers/psgo/psgo.go35
-rw-r--r--vendor/github.com/containers/storage/Makefile3
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/drivers/fsdiff.go1
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go13
-rw-r--r--vendor/github.com/containers/storage/go.mod12
-rw-r--r--vendor/github.com/containers/storage/go.sum30
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/archive.go9
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/cache_linux.go630
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/compressor/compressor.go310
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/compressor/rollsum.go81
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/internal/compression.go32
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/storage_linux.go961
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/idtools.go36
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/idtools_supported.go6
-rw-r--r--vendor/github.com/containers/storage/store.go46
-rw-r--r--vendor/github.com/containers/storage/types/options.go41
-rw-r--r--vendor/github.com/docker/docker/opts/address_pools.go84
-rw-r--r--vendor/github.com/docker/docker/opts/env.go30
-rw-r--r--vendor/github.com/docker/docker/opts/hosts.go183
-rw-r--r--vendor/github.com/docker/docker/opts/hosts_unix.go11
-rw-r--r--vendor/github.com/docker/docker/opts/hosts_windows.go60
-rw-r--r--vendor/github.com/docker/docker/opts/ip.go47
-rw-r--r--vendor/github.com/docker/docker/opts/opts.go348
-rw-r--r--vendor/github.com/docker/docker/opts/quotedstring.go37
-rw-r--r--vendor/github.com/docker/docker/opts/runtime.go79
-rw-r--r--vendor/github.com/docker/docker/opts/ulimit.go81
-rw-r--r--vendor/github.com/docker/go-connections/nat/nat.go28
-rw-r--r--vendor/github.com/docker/go-connections/nat/sort.go4
-rw-r--r--vendor/github.com/docker/go-connections/sockets/proxy.go39
-rw-r--r--vendor/github.com/docker/go-connections/sockets/sockets.go12
-rw-r--r--vendor/github.com/docker/go-connections/sockets/sockets_unix.go13
-rw-r--r--vendor/github.com/docker/go-connections/sockets/sockets_windows.go5
-rw-r--r--vendor/github.com/docker/go-connections/sockets/unix_socket.go116
-rw-r--r--vendor/github.com/docker/go-connections/tlsconfig/config.go31
-rw-r--r--vendor/github.com/docker/go-connections/tlsconfig/versions_go113.go16
-rw-r--r--vendor/github.com/docker/go-connections/tlsconfig/versions_other.go15
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/volume/api.go9
-rw-r--r--vendor/github.com/docker/libnetwork/ipamutils/utils.go135
-rw-r--r--vendor/github.com/felixge/httpsnoop/.gitignore0
-rw-r--r--vendor/github.com/felixge/httpsnoop/.travis.yml6
-rw-r--r--vendor/github.com/felixge/httpsnoop/LICENSE.txt19
-rw-r--r--vendor/github.com/felixge/httpsnoop/Makefile10
-rw-r--r--vendor/github.com/felixge/httpsnoop/README.md94
-rw-r--r--vendor/github.com/felixge/httpsnoop/capture_metrics.go84
-rw-r--r--vendor/github.com/felixge/httpsnoop/docs.go10
-rw-r--r--vendor/github.com/felixge/httpsnoop/go.mod3
-rw-r--r--vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go385
-rw-r--r--vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go243
-rw-r--r--vendor/github.com/google/shlex/go.mod3
-rw-r--r--vendor/github.com/gorilla/handlers/.travis.yml8
-rw-r--r--vendor/github.com/gorilla/handlers/README.md22
-rw-r--r--vendor/github.com/gorilla/handlers/canonical.go5
-rw-r--r--vendor/github.com/gorilla/handlers/compress.go157
-rw-r--r--vendor/github.com/gorilla/handlers/cors.go355
-rw-r--r--vendor/github.com/gorilla/handlers/go.mod5
-rw-r--r--vendor/github.com/gorilla/handlers/go.sum2
-rw-r--r--vendor/github.com/gorilla/handlers/handlers.go287
-rw-r--r--vendor/github.com/gorilla/handlers/logging.go244
-rw-r--r--vendor/github.com/gorilla/handlers/proxy_headers.go23
-rw-r--r--vendor/github.com/gorilla/handlers/recovery.go96
-rw-r--r--vendor/github.com/jinzhu/copier/copier.go125
-rw-r--r--vendor/github.com/klauspost/compress/.goreleaser.yml4
-rw-r--r--vendor/github.com/klauspost/compress/README.md14
-rw-r--r--vendor/github.com/klauspost/compress/flate/deflate.go169
-rw-r--r--vendor/github.com/klauspost/compress/flate/fast_encoder.go2
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go199
-rw-r--r--vendor/github.com/klauspost/compress/flate/huffman_code.go4
-rw-r--r--vendor/github.com/klauspost/compress/flate/inflate.go9
-rw-r--r--vendor/github.com/klauspost/compress/flate/token.go19
-rw-r--r--vendor/github.com/klauspost/compress/huff0/decompress.go234
-rw-r--r--vendor/github.com/klauspost/compress/zstd/bitreader.go15
-rw-r--r--vendor/github.com/klauspost/compress/zstd/bitwriter.go22
-rw-r--r--vendor/github.com/klauspost/compress/zstd/blockdec.go24
-rw-r--r--vendor/github.com/klauspost/compress/zstd/blockenc.go108
-rw-r--r--vendor/github.com/klauspost/compress/zstd/decodeheader.go84
-rw-r--r--vendor/github.com/klauspost/compress/zstd/enc_base.go24
-rw-r--r--vendor/github.com/klauspost/compress/zstd/enc_fast.go139
-rw-r--r--vendor/github.com/klauspost/compress/zstd/encoder_options.go10
-rw-r--r--vendor/github.com/klauspost/compress/zstd/fse_decoder.go2
-rw-r--r--vendor/github.com/klauspost/compress/zstd/fse_encoder.go5
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s1
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s186
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go (renamed from vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go)8
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go4
-rw-r--r--vendor/github.com/klauspost/compress/zstd/seqdec.go4
-rw-r--r--vendor/github.com/mtrmac/gpgme/go.mod3
-rw-r--r--vendor/github.com/opencontainers/runtime-spec/specs-go/config.go53
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/config.go28
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/generate.go55
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go5
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go16
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate.go5
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go1
-rw-r--r--vendor/github.com/openshift/imagebuilder/.travis.yml4
-rw-r--r--vendor/github.com/openshift/imagebuilder/builder.go5
-rw-r--r--vendor/github.com/openshift/imagebuilder/dispatchers.go110
-rw-r--r--vendor/github.com/openshift/imagebuilder/go.mod18
-rw-r--r--vendor/github.com/openshift/imagebuilder/go.sum1003
-rw-r--r--vendor/github.com/openshift/imagebuilder/internals.go2
-rw-r--r--vendor/github.com/openshift/imagebuilder/vendor.conf25
-rw-r--r--vendor/github.com/proglottis/gpgme/.appveyor.yml (renamed from vendor/github.com/mtrmac/gpgme/.appveyor.yml)0
-rw-r--r--vendor/github.com/proglottis/gpgme/.gitignore (renamed from vendor/github.com/mtrmac/gpgme/.gitignore)0
-rw-r--r--vendor/github.com/proglottis/gpgme/.travis.yml (renamed from vendor/github.com/mtrmac/gpgme/.travis.yml)0
-rw-r--r--vendor/github.com/proglottis/gpgme/LICENSE (renamed from vendor/github.com/mtrmac/gpgme/LICENSE)0
-rw-r--r--vendor/github.com/proglottis/gpgme/README.md (renamed from vendor/github.com/mtrmac/gpgme/README.md)0
-rw-r--r--vendor/github.com/proglottis/gpgme/callbacks.go (renamed from vendor/github.com/mtrmac/gpgme/callbacks.go)0
-rw-r--r--vendor/github.com/proglottis/gpgme/data.go (renamed from vendor/github.com/mtrmac/gpgme/data.go)0
-rw-r--r--vendor/github.com/proglottis/gpgme/go.mod3
-rw-r--r--vendor/github.com/proglottis/gpgme/go_gpgme.c (renamed from vendor/github.com/mtrmac/gpgme/go_gpgme.c)0
-rw-r--r--vendor/github.com/proglottis/gpgme/go_gpgme.h (renamed from vendor/github.com/mtrmac/gpgme/go_gpgme.h)5
-rw-r--r--vendor/github.com/proglottis/gpgme/gpgme.go (renamed from vendor/github.com/mtrmac/gpgme/gpgme.go)36
-rw-r--r--vendor/github.com/proglottis/gpgme/unset_agent_info.go (renamed from vendor/github.com/mtrmac/gpgme/unset_agent_info.go)0
-rw-r--r--vendor/github.com/proglottis/gpgme/unset_agent_info_windows.go (renamed from vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go)0
-rw-r--r--vendor/github.com/sylabs/sif/v2/LICENSE.md29
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/arch.go69
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/buffer.go103
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/create.go680
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor.go267
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor_input.go300
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/load.go174
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/select.go210
-rw-r--r--vendor/github.com/sylabs/sif/v2/pkg/sif/sif.go364
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/bar.go93
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go37
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go10
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/bar_option.go5
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go6
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/decor/optimistic_string_writer.go12
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/decor/percentage.go9
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/decor/size_type.go22
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/decor/speed.go3
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/go.mod2
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/go.sum4
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/progress.go34
-rw-r--r--vendor/github.com/vbauerster/mpb/v7/proxyreader.go45
-rw-r--r--vendor/github.com/vishvananda/netlink/.travis.yml20
-rw-r--r--vendor/github.com/vishvananda/netlink/README.md2
-rw-r--r--vendor/github.com/vishvananda/netlink/addr_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/bpf_linux.go24
-rw-r--r--vendor/github.com/vishvananda/netlink/class_linux.go8
-rw-r--r--vendor/github.com/vishvananda/netlink/conntrack_linux.go143
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go353
-rw-r--r--vendor/github.com/vishvananda/netlink/filter.go62
-rw-r--r--vendor/github.com/vishvananda/netlink/filter_linux.go306
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_linux.go14
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_unspecified.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/ipset_linux.go167
-rw-r--r--vendor/github.com/vishvananda/netlink/link.go73
-rw-r--r--vendor/github.com/vishvananda/netlink/link_linux.go182
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh_linux.go34
-rw-r--r--vendor/github.com/vishvananda/netlink/netlink_unspecified.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/netns_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/devlink_linux.go55
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/link_linux.go9
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/lwt_linux.go29
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/nl_linux.go53
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/seg6_linux.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/syscall.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/tc_linux.go105
-rw-r--r--vendor/github.com/vishvananda/netlink/proc_event.go217
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc_linux.go9
-rw-r--r--vendor/github.com/vishvananda/netlink/rdma_link_linux.go51
-rw-r--r--vendor/github.com/vishvananda/netlink/route.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/route_linux.go237
-rw-r--r--vendor/github.com/vishvananda/netlink/rule.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/rule_linux.go5
-rw-r--r--vendor/github.com/vishvananda/netlink/socket_linux.go76
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go2
-rw-r--r--vendor/golang.org/x/net/http2/server.go10
-rw-r--r--vendor/golang.org/x/net/http2/transport.go78
-rw-r--r--vendor/golang.org/x/net/http2/writesched.go4
-rw-r--r--vendor/golang.org/x/net/http2/writesched_random.go6
-rw-r--r--vendor/golang.org/x/net/internal/socks/client.go168
-rw-r--r--vendor/golang.org/x/net/internal/socks/socks.go317
-rw-r--r--vendor/golang.org/x/net/proxy/dial.go54
-rw-r--r--vendor/golang.org/x/net/proxy/direct.go31
-rw-r--r--vendor/golang.org/x/net/proxy/per_host.go155
-rw-r--r--vendor/golang.org/x/net/proxy/proxy.go149
-rw-r--r--vendor/golang.org/x/net/proxy/socks5.go42
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux.go23
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_386.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_arm.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_mips.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go3
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_386.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go1
-rw-r--r--vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go1
-rw-r--r--vendor/golang.org/x/sys/unix/ztypes_linux.go66
-rw-r--r--vendor/golang.org/x/sys/windows/syscall_windows.go2
-rw-r--r--vendor/golang.org/x/sys/windows/types_windows.go39
-rw-r--r--vendor/golang.org/x/sys/windows/zsyscall_windows.go14
-rw-r--r--vendor/modules.txt63
550 files changed, 18709 insertions, 5580 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index c33ed9c0c..77e024a14 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -7,6 +7,10 @@ env:
####
# Name of the ultimate destination branch for this CI run, PR or post-merge.
DEST_BRANCH: "main"
+ # Netavark branch to use when TEST_ENVIRON=host-netavark
+ NETAVARK_BRANCH: "main"
+ # Aardvark branch to use
+ AARDVARK_BRANCH: "main"
# Overrides default location (/tmp/cirrus) for repo clone
GOPATH: &gopath "/var/tmp/go"
GOBIN: "${GOPATH}/bin"
@@ -20,6 +24,11 @@ env:
# Runner statistics log file path/name
STATS_LOGFILE_SFX: 'runner_stats.log'
STATS_LOGFILE: '$GOSRC/${CIRRUS_TASK_NAME}-${STATS_LOGFILE_SFX}'
+ # Netavark/aardvark location/options when TEST_ENVIRON=host-netavark
+ NETAVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/netavark/success/binary.zip?branch=${NETAVARK_BRANCH}"
+ NETAVARK_DEBUG: 0 # set non-zero to use the debug-mode binary
+ AARDVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/aardvark-dns/success/binary.zip?branch=${AARDVARK_BRANCH}"
+ AARDVARK_DEBUG: 0 # set non-zero to use the debug-mode binary
####
#### Cache-image names to test with (double-quotes around names are critical)
@@ -44,7 +53,7 @@ env:
#### N/B: Required ALL of these are set for every single task.
####
TEST_FLAVOR: # int, sys, ext_svc, validate, automation, etc.
- TEST_ENVIRON: host # 'host' or 'container'
+ TEST_ENVIRON: host # 'host', 'host-netavark', or 'container'
PODBIN_NAME: podman # 'podman' or 'remote'
PRIV_NAME: root # 'root' or 'rootless'
DISTRO_NV: # any {PRIOR_,}{FEDORA,UBUNTU}_NAME value
@@ -218,7 +227,8 @@ validate_task:
bindings_task:
name: "Test Bindings"
alias: bindings
- only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
+ # Don't run for [CI:DOCS] or [CI:BUILD]
+ only_if: &not_build $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' && $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*'
skip: *branches_and_tags
depends_on:
- build
@@ -298,7 +308,8 @@ consistency_task:
alt_build_task:
name: "$ALT_NAME"
alias: alt_build
- only_if: *not_docs
+ # Don't run for [CI:DOCS]; DO run for [CI:BUILD]
+ only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
depends_on:
- build
env:
@@ -327,6 +338,7 @@ alt_build_task:
osx_alt_build_task:
name: "OSX Cross"
alias: osx_alt_build
+ only_if: *not_docs
depends_on:
- build
env:
@@ -352,7 +364,7 @@ docker-py_test_task:
name: Docker-py Compat.
alias: docker-py_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
depends_on:
- build
gce_instance: *standardvm
@@ -373,7 +385,7 @@ unit_test_task:
name: "Unit tests on $DISTRO_NV"
alias: unit_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
depends_on:
- validate
matrix:
@@ -398,7 +410,7 @@ unit_test_task:
apiv2_test_task:
name: "APIv2 test on $DISTRO_NV"
alias: apiv2_test
- only_if: *not_docs
+ only_if: *not_build
skip: *tags
depends_on:
- validate
@@ -419,7 +431,7 @@ apiv2_test_task:
compose_test_task:
name: "compose test on $DISTRO_NV ($PRIV_NAME)"
alias: compose_test
- only_if: *not_docs
+ only_if: *not_build
skip: *tags
depends_on:
- validate
@@ -446,7 +458,7 @@ local_integration_test_task: &local_integration_test_task
# <int.|sys.> <podman|remote> <Distro NV> <root|rootless>
name: &std_name_fmt "$TEST_FLAVOR $PODBIN_NAME $DISTRO_NV $PRIV_NAME $TEST_ENVIRON"
alias: local_integration_test
- only_if: *not_docs
+ only_if: *not_build
skip: *branches_and_tags
depends_on:
- unit_test
@@ -482,7 +494,7 @@ remote_integration_test_task:
container_integration_test_task:
name: *std_name_fmt
alias: container_integration_test
- only_if: *not_docs
+ only_if: *not_build
skip: *branches_and_tags
depends_on:
- unit_test
@@ -509,11 +521,56 @@ container_integration_test_task:
always: *int_logs_artifacts
+# Run the integration tests using the latest upstream build of netavark.
+netavark_integration_test_task:
+ name: "Netavark integration" # using *std_name_fmt here is unreadable
+ alias: netavark_integration_test
+ only_if: *not_build
+ skip: *branches_and_tags
+ depends_on:
+ - unit_test
+ gce_instance: *standardvm
+ env:
+ DISTRO_NV: ${FEDORA_NAME}
+ _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID}
+ VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
+ CTR_FQIN: ${FEDORA_CONTAINER_FQIN}
+ TEST_FLAVOR: int
+ TEST_ENVIRON: host-netavark
+ clone_script: *noop # Comes from cache
+ gopath_cache: *ro_gopath_cache
+ setup_script: *setup
+ main_script: *main
+ always: *int_logs_artifacts
+
+
+netavark_system_test_task:
+ name: "Netavark system"
+ alias: netavark_system_test
+ skip: *tags
+ only_if: *not_build
+ depends_on:
+ - netavark_integration_test
+ gce_instance: *standardvm
+ env:
+ DISTRO_NV: ${FEDORA_NAME}
+ _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID}
+ VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
+ CTR_FQIN: ${FEDORA_CONTAINER_FQIN}
+ TEST_ENVIRON: host-netavark
+ TEST_FLAVOR: sys
+ clone_script: *noop # Comes from cache
+ gopath_cache: *ro_gopath_cache
+ setup_script: *setup
+ main_script: *main
+ always: *logs_artifacts
+
+
# Execute most integration tests as a regular (non-root) user.
rootless_integration_test_task:
name: *std_name_fmt
alias: rootless_integration_test
- only_if: *not_docs
+ only_if: *not_build
skip: *branches_and_tags
depends_on:
- unit_test
@@ -538,7 +595,7 @@ local_system_test_task: &local_system_test_task
name: *std_name_fmt
alias: local_system_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
depends_on:
- local_integration_test
matrix: *platform_axis
@@ -561,11 +618,33 @@ remote_system_test_task:
TEST_FLAVOR: sys
PODBIN_NAME: remote
+
+rootless_remote_system_test_task:
+ <<: *local_system_test_task
+ alias: rootless_remote_system_test
+ depends_on:
+ - remote_integration_test
+ matrix:
+ # Minimal sanity testing: only the latest Fedora
+ - env:
+ DISTRO_NV: ${FEDORA_NAME}
+ # Not used here, is used in other tasks
+ VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME}
+ CTR_FQIN: ${FEDORA_CONTAINER_FQIN}
+ # ID for re-use of build output
+ _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID}
+ gce_instance: *standardvm
+ env:
+ TEST_FLAVOR: sys
+ PODBIN_NAME: remote
+ PRIV_NAME: rootless
+
+
buildah_bud_test_task:
name: *std_name_fmt
alias: buildah_bud_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
depends_on:
- local_integration_test
env:
@@ -589,11 +668,12 @@ buildah_bud_test_task:
main_script: *main
always: *int_logs_artifacts
+
rootless_system_test_task:
name: *std_name_fmt
alias: rootless_system_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
depends_on:
- rootless_integration_test
matrix: *platform_axis
@@ -607,11 +687,12 @@ rootless_system_test_task:
main_script: *main
always: *logs_artifacts
+
rootless_gitlab_test_task:
name: *std_name_fmt
alias: rootless_gitlab_test
skip: *tags
- only_if: *not_docs
+ only_if: *not_build
# Community-maintained downstream test may fail unexpectedly.
# Ref. repository: https://gitlab.com/gitlab-org/gitlab-runner
# If necessary, uncomment the next line and file issue(s) with details.
@@ -634,11 +715,12 @@ rootless_gitlab_test_task:
type: text/xml
format: junit
+
upgrade_test_task:
name: "Upgrade test: from $PODMAN_UPGRADE_FROM"
alias: upgrade_test
skip: *tags
- only_if: $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' || $CIRRUS_CRON != ''
+ only_if: *not_build
depends_on:
- local_system_test
matrix:
@@ -663,6 +745,7 @@ upgrade_test_task:
main_script: *main
always: *logs_artifacts
+
# This task is critical. It updates the "last-used by" timestamp stored
# in metadata for all VM images. This mechanism functions in tandem with
# an out-of-band pruning operation to remove disused VM images.
@@ -711,11 +794,14 @@ success_task:
- compose_test
- local_integration_test
- remote_integration_test
- - rootless_integration_test
- container_integration_test
+ - netavark_integration_test
+ - netavark_system_test
+ - rootless_integration_test
- local_system_test
- remote_system_test
- rootless_system_test
+ - rootless_remote_system_test
- rootless_gitlab_test
- upgrade_test
- buildah_bud_test
@@ -756,7 +842,10 @@ release_task:
release_test_task:
name: "Optional Release Test"
alias: release_test
- only_if: $CIRRUS_PR != ''
+ # Release-PRs always include "release" or "Bump" in the title
+ only_if: $CIRRUS_CHANGE_TITLE =~ '.*((release)|(bump)).*'
+ # Allow running manually only as part of release-related builds
+ # see RELEASE_PROCESS.md
trigger_type: manual
depends_on:
- success
diff --git a/.copr/Makefile b/.copr/Makefile
deleted file mode 100644
index ff99cd5c6..000000000
--- a/.copr/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/make -f
-mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
-current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
-outdir := $(CURDIR)
-topdir := $(CURDIR)/rpmbuild
-SHORT_COMMIT ?= $(shell git rev-parse --short=8 HEAD)
-
-export GO111MODULE=off
-
-srpm:
- mkdir -p $(topdir)
- sh $(current_dir)/prepare.sh
- rpmbuild -bs -D "dist %{nil}" -D "_sourcedir build/" -D "_srcrpmdir $(outdir)" -D "_topdir $(topdir)" --nodeps ${extra_arg:-""} contrib/spec/podman.spec
-
-build_binary:
- mkdir -p $(topdir)
- rpmbuild --rebuild -D "_rpmdir $(outdir)" -D "_topdir $(topdir)" ${extra_arg:-""} $(outdir)/podman-*.git$(SHORT_COMMIT).src.rpm
-
-clean:
- rm -fr rpms
- rm -fr conmon
diff --git a/.copr/prepare.sh b/.copr/prepare.sh
deleted file mode 100644
index de12a0d56..000000000
--- a/.copr/prepare.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh -euf
-set -euxo pipefail
-OS_TEST=${OS_TEST:=0}
-
-if [ ! -e /usr/bin/git ]; then
- dnf -y install git-core
-fi
-
-if [ -f $(git rev-parse --git-dir)/shallow ]; then
- git fetch --unshallow
-fi
-
-COMMIT=$(git rev-parse HEAD)
-COMMIT_SHORT=$(git rev-parse --short=8 HEAD)
-COMMIT_NUM=$(git rev-list HEAD --count)
-COMMIT_DATE=$(date +%s)
-BR="#BuildRequires: golang-bin"
-NEWBR="BuildRequires: golang-bin"
-
-
-sed "s,#COMMIT#,${COMMIT},;
- s,#SHORTCOMMIT#,${COMMIT_SHORT},;
- s,#COMMITNUM#,${COMMIT_NUM},;
- s,#COMMITDATE#,${COMMIT_DATE}," \
- contrib/spec/podman.spec.in > contrib/spec/podman.spec
-
-if [ ${OS_TEST} -eq 0 ]; then
- sed -i "s/${BR}/${NEWBR}/g" contrib/spec/podman.spec
-fi
-
-mkdir -p build/
-git archive --prefix "podman-${COMMIT_SHORT}/" --format "tar.gz" HEAD -o "build/podman-${COMMIT_SHORT}.tar.gz"
-if [ ! -d conmon ]; then
- git clone -n --quiet https://github.com/containers/conmon
-fi
-pushd conmon
-git checkout --detach d532caebc788fafdd2a305b68cd1983b4039bea4
-git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
-popd
diff --git a/.github/actions/check_cirrus_cron/cron_failures.sh b/.github/actions/check_cirrus_cron/cron_failures.sh
index 16419c6d6..4fb3af98f 100755
--- a/.github/actions/check_cirrus_cron/cron_failures.sh
+++ b/.github/actions/check_cirrus_cron/cron_failures.sh
@@ -22,7 +22,7 @@ mkdir -p artifacts
cat > ./artifacts/query_raw.json << "EOF"
{"query":"
query CronNameStatus($owner: String!, $repo: String!) {
- githubRepository(owner: $owner, name: $repo) {
+ ownerRepository(platform: \"LINUX\", owner: $owner, name: $repo) {
cronSettings {
name
lastInvocationBuild {
@@ -75,7 +75,7 @@ fi
# e.x. reply.json
# {
# "data": {
-# "githubRepository": {
+# "ownerRepository": {
# "cronSettings": [
# {
# "name": "Keepalive_v2.0",
@@ -102,7 +102,7 @@ fi
# }
# }
# }
-_filt='.data.githubRepository.cronSettings | map(select(.lastInvocationBuild.status=="FAILED") | { name:.name, id:.lastInvocationBuild.id} | join(" ")) | join("\n")'
+_filt='.data.ownerRepository.cronSettings | map(select(.lastInvocationBuild.status=="FAILED") | { name:.name, id:.lastInvocationBuild.id} | join(" ")) | join("\n")'
jq --raw-output "$_filt" ./artifacts/reply.json > "$NAME_ID_FILEPATH"
echo "<Cron Name> <Failed Build ID>"
diff --git a/.github/issue-labeler.yml b/.github/issue-labeler.yml
new file mode 100644
index 000000000..e285749a9
--- /dev/null
+++ b/.github/issue-labeler.yml
@@ -0,0 +1,13 @@
+# List of labels which should be assigned to issues based on a regex
+windows:
+ # info prints OsArch: ...
+ # version prints OS/Arch: ...
+ - 'O[Ss]\/?Arch:\s*windows'
+macos:
+ # info prints OsArch: ...
+ # version prints OS/Arch: ...
+ - 'O[Ss]\/?Arch:\s*darwin'
+
+remote:
+ # we cannot use multiline regex so we check for serviceIsRemote in podman info
+ - 'serviceIsRemote:\strue'
diff --git a/.github/workflows/check_cirrus_cron.yml b/.github/workflows/check_cirrus_cron.yml
index 65c483c96..5c206ae2f 100644
--- a/.github/workflows/check_cirrus_cron.yml
+++ b/.github/workflows/check_cirrus_cron.yml
@@ -19,9 +19,8 @@ env:
# Debug-mode can reveal secrets, only enable by a secret value.
# Ref: https://help.github.com/en/actions/configuring-and-managing-workflows/managing-a-workflow-run#enabling-step-debug-logging
ACTIONS_STEP_DEBUG: '${{ secrets.ACTIONS_STEP_DEBUG }}'
- # File with CSV listing of zero or more e-mail addresses for delivery
- # of daily failure notice e-mails.
- FAILMAILCSV: './contrib/cirrus/cron-fail_addrs.csv'
+ # CSV listing of e-mail addresses for delivery failure or error notices
+ RCPTCSV: rh.container.bot@gmail.com,podman-monitor@lists.podman.io
# Filename for table of cron-name to build-id data
# (must be in $GITHUB_WORKSPACE/artifacts/)
NAME_ID_FILEPATH: './artifacts/name_id.txt'
@@ -60,10 +59,6 @@ jobs:
) > ./artifacts/email_body.txt
- if: steps.cron.outputs.failures > 0
- id: mailto
- run: printf "::set-output name=csv::%s\n" $(cat "$FAILMAILCSV")
-
- - if: steps.mailto.outputs.csv != ''
name: Send failure notification e-mail
# Ref: https://github.com/dawidd6/action-send-mail
uses: dawidd6/action-send-mail@v2.2.2
@@ -73,7 +68,7 @@ jobs:
username: ${{secrets.ACTION_MAIL_USERNAME}}
password: ${{secrets.ACTION_MAIL_PASSWORD}}
subject: Cirrus-CI cron build failures on ${{github.repository}}
- to: ${{steps.mailto.outputs.csv}}
+ to: ${{env.RCPTCSV}}
from: ${{secrets.ACTION_MAIL_SENDER}}
body: file://./artifacts/email_body.txt
@@ -82,3 +77,16 @@ jobs:
with:
name: ${{ github.job }}_artifacts
path: artifacts/*
+
+ - if: failure()
+ name: Send error notification e-mail
+ uses: dawidd6/action-send-mail@v2.2.2
+ with:
+ server_address: ${{secrets.ACTION_MAIL_SERVER}}
+ server_port: 465
+ username: ${{secrets.ACTION_MAIL_USERNAME}}
+ password: ${{secrets.ACTION_MAIL_PASSWORD}}
+ subject: Github workflow error on ${{github.repository}}
+ to: ${{env.RCPTCSV}}
+ from: ${{secrets.ACTION_MAIL_SENDER}}
+ body: "Job failed: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}"
diff --git a/.github/workflows/issue-labeler.yml b/.github/workflows/issue-labeler.yml
new file mode 100644
index 000000000..ee9785d23
--- /dev/null
+++ b/.github/workflows/issue-labeler.yml
@@ -0,0 +1,15 @@
+name: "Issue Labeler"
+on:
+ issues:
+ types: [opened, edited]
+
+jobs:
+ triage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: github/issue-labeler@v2.0
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ configuration-path: .github/issue-labeler.yml
+ not-before: 2022-01-27T00:00:00Z
+ enable-versioned-regex: 0
diff --git a/Makefile b/Makefile
index 6482378cd..9e9b3676e 100644
--- a/Makefile
+++ b/Makefile
@@ -186,6 +186,13 @@ ifdef HOMEBREW_PREFIX
endif
endif
+# win-sshproxy is checked out manually to keep from pulling in gvisor and it's transitive
+# dependencies. This is only used for the Windows installer task (podman.msi), which must
+# include this lightweight helper binary.
+#
+GV_GITURL=git://github.com/containers/gvisor-tap-vsock.git
+GV_SHA=e943b1806d94d387c4c38d96719432d50a84bbd0
+
###
### Primary entry-point targets
###
@@ -275,7 +282,7 @@ test/version/version: .gopathok version/version.go
.PHONY: codespell
codespell:
- codespell -S bin,vendor,.git,go.sum,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.ps1,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w
+ codespell -S bin,vendor,.git,go.sum,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.ps1,*.tar,swagger.yaml,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w
.PHONY: validate
validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check tests-included tests-expect-exit
@@ -528,7 +535,7 @@ run-docker-py-tests:
.PHONY: localunit
localunit: test/goecho/goecho test/version/version
rm -rf ${COVERAGE_PATH} && mkdir -p ${COVERAGE_PATH}
- $(GOBIN)/ginkgo \
+ UNIT=1 $(GOBIN)/ginkgo \
-r \
$(TESTFLAGS) \
--skipPackage test/e2e,pkg/apparmor,pkg/bindings,hack \
@@ -547,6 +554,7 @@ test: localunit localintegration remoteintegration localsystem remotesystem ##
.PHONY: ginkgo-run
ginkgo-run:
+ $(GOBIN)/ginkgo version
$(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(TAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. $(HACK)
.PHONY: ginkgo
@@ -663,7 +671,7 @@ podman-release-%.tar.gz: test/version/version
else \
$(MAKE) GOOS=$(GOOS) GOARCH=$(GOARCH) binaries; \
fi
- $(MAKE) $(_DSTARGS) install.bin-nobuild install.remote-nobuild install.man install.systemd
+ $(MAKE) $(_DSTARGS) install.bin install.remote install.man install.systemd
tar -czvf $@ --xattrs -C "$(TMPDIR)" "./$(SUBDIR)"
if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
-rm -rf "$(TMPDIR)"
@@ -686,7 +694,7 @@ podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$
fi
cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/"
cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/"
- $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote-nobuild
+ $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote
cd "$(TMPDIR)" && \
zip --recurse-paths "$(CURDIR)/$@" "./"
if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
@@ -695,7 +703,7 @@ podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$
.PHONY: podman.msi
podman.msi: test/version/version ## Build podman-remote, package for installation on Windows
$(MAKE) podman-v$(RELEASE_NUMBER).msi
-podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs podman-winpath
+podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs podman-winpath win-sshproxy
$(eval DOCFILE := docs/build/remote/windows)
find $(DOCFILE) -print | \
wixl-heat --var var.ManSourceDir --component-group ManFiles \
@@ -704,12 +712,22 @@ podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs
wixl -D VERSION=$(call err_if_empty,RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
-o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx --arch x64
+# Checks out and builds win-sshproxy helper. See comment on GV_GITURL declaration
+.PHONY: win-sshproxy
+win-sshproxy: test/version/version
+ rm -rf tmp-gv; mkdir tmp-gv
+ (cd tmp-gv; \
+ git init; \
+ git remote add origin $(GV_GITURL); \
+ git fetch --depth 1 origin $(GV_SHA); \
+ git checkout FETCH_HEAD; make win-sshproxy)
+ mkdir -p bin/windows/
+ cp tmp-gv/bin/win-sshproxy.exe bin/windows/
+ rm -rf tmp-gv
+
.PHONY: package
package: ## Build rpm packages
- ## TODO(ssbarnea): make version number predictable, it should not change
- ## on each execution, producing duplicates.
- rm -rf build/* *.src.rpm ~/rpmbuild/RPMS/*
- ./contrib/build_rpm.sh
+ rpkg local
###
### Installation targets
@@ -731,8 +749,8 @@ install: .gopathok install.bin install.remote install.man install.systemd ## In
install.catatonit:
./hack/install_catatonit.sh
-.PHONY: install.remote-nobuild
-install.remote-nobuild:
+.PHONY: install.remote
+install.remote:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR)
install ${SELINUXOPT} -m 755 $(SRCBINDIR)/podman$(BINSFX) \
$(DESTDIR)$(BINDIR)/podman$(BINSFX)
@@ -740,11 +758,8 @@ install.remote-nobuild:
chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman-remote \
bin/podman-remote
-.PHONY: install.remote
-install.remote: podman-remote install.remote-nobuild
-
-.PHONY: install.bin-nobuild
-install.bin-nobuild:
+.PHONY: install.bin
+install.bin:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR)
install ${SELINUXOPT} -m 755 bin/podman $(DESTDIR)$(BINDIR)/podman
test -z "${SELINUXOPT}" || chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman bin/podman
@@ -754,20 +769,14 @@ install.bin-nobuild:
install ${SELINUXOPT} -m 755 -d ${DESTDIR}${TMPFILESDIR}
install ${SELINUXOPT} -m 644 contrib/tmpfile/podman.conf ${DESTDIR}${TMPFILESDIR}/podman.conf
-.PHONY: install.bin
-install.bin: podman rootlessport install.bin-nobuild
-
-.PHONY: install.man-nobuild
-install.man-nobuild:
+.PHONY: install.man
+install.man:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5
install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES_DEST)) -t $(DESTDIR)$(MANDIR)/man1
install ${SELINUXOPT} -m 644 $(filter %.5,$(MANPAGES_DEST)) -t $(DESTDIR)$(MANDIR)/man5
install ${SELINUXOPT} -m 644 docs/source/markdown/links/*1 -t $(DESTDIR)$(MANDIR)/man1
-.PHONY: install.man
-install.man: docs install.man-nobuild
-
.PHONY: install.completions
install.completions:
install ${SELINUXOPT} -d -m 755 ${DESTDIR}${BASHINSTALLDIR}
@@ -788,16 +797,13 @@ install.docker:
install ${SELINUXOPT} -m 755 -d ${DESTDIR}${SYSTEMDDIR} ${DESTDIR}${USERSYSTEMDDIR} ${DESTDIR}${TMPFILESDIR}
install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-docker.conf -t ${DESTDIR}${TMPFILESDIR}
-.PHONY: install.docker-docs-nobuild
-install.docker-docs-nobuild:
+.PHONY: install.docker-docs
+install.docker-docs:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1
install ${SELINUXOPT} -m 644 docs/build/man/docker*.1 -t $(DESTDIR)$(MANDIR)/man1
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5
install ${SELINUXOPT} -m 644 docs/build/man/docker*.5 -t $(DESTDIR)$(MANDIR)/man5
-.PHONY: install.docker-docs
-install.docker-docs: docker-docs install.docker-docs-nobuild
-
.PHONY: install.docker-full
install.docker-full: install.docker install.docker-docs
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 04bd196be..18aaeecfd 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,263 @@
# Release Notes
+## 4.0.0
+### Features
+- Podman has seen an extensive rewrite of its network stack to add support for Netavark, a new tool for configuring container networks, in addition to the existing CNI stack. Netavark will be default on new installations when it is available.
+- The `podman network connect` command now supports three new options, `--ip`, `--ip6`, and `--mac-address`, to specify configuration for the new network that will be attached.
+- The `--network` option to `podman create`, `podman pod create`, `podman run`, and `podman play kube` can now, when specifying a network name, also specify advanced network options such as `alias`, `ip`, `mac`, and `interface_name`, allowing advanced configuration of networks when creating containers connected to more than one network.
+- The `podman play kube` command can now specify the `--net` option multiple times, to connect created containers and pods to multiple networks.
+- The `podman create`, `podman pod create`, and `podman run` commands now support a new option, `--ip6`, to specify a static IPv6 address for the created container or pod to use.
+- Macvlan networks can now configure the mode of the network via the `-o mode=` option.
+- When using the CNI network stack, a new network driver, `ipvlan`, is now available.
+- The `podman info` command will now print the network backend in use (Netavark or CNI).
+- The network backend to use can be now be specified in `containers.conf` via the `network_backend` field. Please note that it is not recommended to switch backends while containers exist, and a system reboot is recommended after doing so.
+- All Podman commands now support a new option, `--noout`, that suppresses all output to STDOUT.
+- All commands that can remove containers (`podman rm --force`, `podman pod rm --force`, `podman volume rm --force`, `podman network rm --force`) now accept a `--time` option to specify the timeout on stopping the container before resorting to `SIGKILL` (identical to the `--time` flag to `podman stop`).
+- The `podman run` and `podman create` commands now support a new option, `--passwd`, that uses the `/etc/passwd` and `/etc/groups` files from the image in the created container without changes by Podman ([#11805](https://github.com/containers/podman/issues/11805)).
+- The `podman run` and `podman create` commands now support a new option, `--hostuser`, that creates one or more users in the container based on users from the host (e.g. with matching username, UID, and GID).
+- The `podman create` and `podman run` commands now support two new options, `--unsetenv` and `--unsetenv-all`, to clear default environment variables set by Podman and by the container image ([#11836](https://github.com/containers/podman/issues/11836)).
+- The `podman rm` command now supports a new option, `--depend`, which recursively removes a given container and all containers that depend on it ([#10360](https://github.com/containers/podman/issues/10360)).
+- All commands that support filtering their output based on labels (e.g. `podman volume ls`, `podman ps`) now support labels specified using regular expressions (e.g. `--filter label=some.prefix.com/key/*`).
+- The `podman pod create` command now supports the `--volume` option, allowing volumes to be specified that will be mounted automatically to all containers in the pod ([#10379](https://github.com/containers/podman/issues/10379)).
+- The `podman pod create` command now supports the `--device` option, allowing devices to be specified that will be mounted automatically to all containers in the pod.
+- The `podman pod create` command now supports the `--volumes-from` option, allowing volumes from an existing Podman container to be mounted automatically to all containers in the pod.
+- The `podman pod create` command now supports the `--security-opt` option, allowing security settings (e.g. disabling SELinux or Seccomp) to be configured automatically for all containers in the pod ([#12173](https://github.com/containers/podman/issues/12173)).
+- The `podman pod create` command now supports the `--sysctl` option, allowing sysctls to be configured automatically for all containers in the pod.
+- The `podman events` command now supports the `--no-trunc` option, which will allow short container IDs to be displayed instead of the default full IDs. The flag defaults to true, so full IDs remain the default ([#8941](https://github.com/containers/podman/issues/8941)).
+- The `podman machine init` command now supports a new VM type, `wsl`, available only on Windows; this uses WSL as a backend for `podman machine`, instead of creating a separate VM and managing it via QEMU ([#12503](https://github.com/containers/podman/pull/12503)).
+- The `podman machine init` command now supports a new option, `--now`, to start the VM immediately after creating it.
+- The `podman machine init` command now supports a new option, `--volume`, to mount contents from the host into the created virtual machine.
+- Virtual machines created by `podman machine` now automatically mount certificates from the host's keychain into the virtual machine ([#11507](https://github.com/containers/podman/issues/11507)).
+- Virtual machines created by `podman machine` now automatically propagate standard proxy environment variables from the host into the virtual machine, including copying any required certificates from `SSL_FILE_CERT` into the VM.
+- The `podman machine ssh` command now supports a new option, `--username`, to specify the username to connect to the VM with.
+- Port forwarding from VMs created using `podman machine` now supports ports specified using custom host IPs (e.g. `-p 127.0.0.1:8080:80`), the UDP protocol, and containers created using the `slirp4netns` network mode ([#11528](https://github.com/containers/podman/issues/11528) and [#11728](https://github.com/containers/podman/issues/11728)).
+- The `podman system connection rm` command supports a new option, `--all`, to remove all available connections ([#12018](https://github.com/containers/podman/issues/12018)).
+- The `podman system service` command's default timeout is now configured via `containers.conf` (using the `service_timeout` field) instead of hardcoded to 5 seconds.
+- The `--mount type=devpts` option to `podman create` and `podman run` now supports new options: `uid`, `gid`, `mode`, and `max`.
+- The `--volume` option to `podman create` and `podman run` now supports a new option, `:idmap`, which using an ID mapping filesystem to allow multiple containers with disjoint UID and GID ranges mapped into them access the same volume ([#12154](https://github.com/containers/podman/issues/12154)).
+- The `U` option for volumes, which changes the ownership of the mounted volume to ensure the user running in the container can access it, can now be used with the `--mount` option to `podman create` and `podman run`, as well as the `--volume` option where it was already available.
+- The `:O` option for volumes, which specifies that an overlay filesystem will be mounted over the volume and ensures changes do not persist, is now supported with named volumes as well as bind mounts.
+- Podman containers created from a user-specified root filesystem (via `--rootfs`) can now create an overlay filesystem atop the user-specified rootfs which ensures changes will not persist by suffixing the user-specified root filesystem with `:O`.
+- The `podman save` command has a new option, `--uncompressed`, which saves the layers of the image without compression ([#11613](https://github.com/containers/podman/issues/11613)).
+- Podman supports a new log driver for containers, `passthrough`, which logs all output directly to the STDOUT and STDERR of the `podman` command; it is intended for use in systemd-managed containers.
+- The `podman build` command now supports two new options, `--unsetenv` and `--all-platforms`.
+- The `podman image prune` command now supports a new option, `--external`, which allows containers not created by Podman (e.g. temporary containers from Buildah builds) to be pruned ([#11472](https://github.com/containers/podman/issues/11472)).
+- Two new aliases for `podman image prune` have been added for Docker compatibility: `podman builder prune` and `podman buildx prune`.
+- The `podman play kube` command now supports a new option, `--no-hosts`, which uses the `/etc/hosts` file from the image in all generated containers, preventing any modifications to the hosts file from Podman ([#9500](https://github.com/containers/podman/issues/9500)).
+- The `podman play kube` command now supports a new option, `--replace`, which will replace any existing containers and pods with the same names as the containers and pods that will be created by the command ([#11481](https://github.com/containers/podman/issues/11481)).
+- The `podman play kube` command now supports a new option, `--log-opt`, which allows the logging configuration of generated containers and pods to be adjusted ([#11727](https://github.com/containers/podman/issues/11727)).
+- The `podman play kube` command now supports Kubernetes YAML that specifies volumes from a configmap.
+- The `podman generate systemd` command now supports a new option, `--template`, to generate template unit files.
+- The `podman generate systemd` command now supports a new option, `--start-timeout`, to override the default start timeout for generated unit files ([#11618](https://github.com/containers/podman/issues/11618)).
+- The `podman generate systemd` command now supports a new option, `--restart-sec`, to override the default time before a failed unit is restarted by systemd for generated unit files.
+- The `podman generate systemd` command now supports three new options, `--wants`, `--after`, and `--requires`, which allow detailed control of systemd dependencies in generated unit files.
+- The `podman container checkpoint` and `podman container restore` commands can now print statistics about the checkpoint operation via a new option, `--print-stats`.
+- The `podman container checkpoint` and `podman container restore` commands can now checkpoint and restore containers which make use of file locks via a new option, `--file-locks`.
+- The `podman container restore` command can now be used with containers created using the host IPC namespace (`--ipc=host`).
+- The `podman container checkpoint` and `podman container restore` commands now handle checkpointing and restoring the contents of `/dev/shm`.
+- The `podman container checkpoint` and `podman container restore` commands are now supported with the remote Podman client ([#12007](https://github.com/containers/podman/issues/12007)).
+- The `podman inspect` command on containers now includes additional output fields for checkpointed and restored containers, including information about when the container was checkpointed or restored, and the path to the checkpoint/restore log.
+- The `podman secret list` command now supports a new option, `--filter`, to filter what secrets are returned.
+- The `podman image scp` command can now be used to transfer images between users (both root and rootless) on the same system, without requiring `sshd`.
+- The `podman image sign` command now supports a new option, `--authfile`, to specify an alternative path to authentication credentials ([#10866](https://github.com/containers/podman/issues/10866)).
+- The `podman load` command now supports downloading files via HTTP and HTTPS if a URL is given ([#11970](https://github.com/containers/podman/issues/11970)).
+- The `podman push` command now supports a new option, `--compression-format`, to choose the compression algorithm used to compress image layers.
+- The `podman volume create` command now allows volumes using the `local` driver that require mounting to be used by non-root users. This allows `tmpfs` and `bind` volumes to be created by non-root users ([#12013](https://github.com/containers/podman/issues/12013)).
+- A new command, `podman dial-stdio`, has been added; this command should not be invoked directly, but is used by some clients of the Docker Remote API, and is provided for Docker compatibility ([#11668](https://github.com/containers/podman/issues/11668)).
+
+### Breaking Changes
+- Podman v4.0 will perform several schema migrations in the Podman database when it is first run. These schema migrations will cause Podman v3.x and earlier to be unable to read certain network configuration information from the database, so downgrading from Podman v4.0 to an earlier version will cause containers to lose their static IP, MAC address, and port bindings.
+- All endpoints of the Docker-compatible API now enforce that all image shortnames will be resolved to the Docker Hub for improved Docker compatibility. This behavior can be turned off via the `compat_api_enforce_docker_hub` option in `containers.conf` ([#12320](https://github.com/containers/podman/issues/12320)).
+- The Podman APIs for Manifest List and Network operations have been completely rewritten to address issues and inconsistencies in the previous APIs.
+- The `podman rm --depends`, `podman rmi --force`, and `podman network rm --force` commands can now remove pods if a they need to remove an infra container (e.g. `podman rmi --force` on the infra image will remove all pods and infra containers). Previously, any command that tried to remove an infra container would error.
+- If the `CONTAINER_HOST` environment variable is set, Podman will default to connecting to the remote Podman service specified by the environment variable, instead of running containers locally ([#11196](https://github.com/containers/podman/issues/11196)).
+- Healthcheck information from `podman inspect` on a container has had its JSON tag renamed from `Healthcheck` to `Health` for improved Docker compatibility. An alias has been added so that using the old name with the `--format` option will still work ([#11645](https://github.com/containers/podman/issues/11645)).
+- Secondary IP and IPv6 addresses from `podman inspect` on a container (`SecondaryIPAddresses` and `SecondaryIPv6Addresses`) have been changed from arrays of strings to arrays of structs for improved Docker compatibility (the struct now includes IP address and prefix length).
+- The `podman volume rm --force` command will now remove containers that depend on the volume that are running (previously, it would only remove stopped containers).
+- The output of the `podman search` command has been altered to remove the Index, Stars, and Automated columns, as these were not used by registries that are not Dockerhub.
+- The `host.containers.internal` entry in `/etc/hosts` for rootless containers now points to a public IP address of the host machine, to ensure the container can reach the host (the previous value, a slirp4netns address, did not actually point to the host) ([#12000](https://github.com/containers/podman/issues/12000)).
+- Containers created in pods that have an infra container can no longer independently configure a user namespace via `--uidmap` and `--gidmap` ([#12669](https://github.com/containers/podman/issues/12669)).
+- Several container states have been renamed internally - for example, the previous `Configured` state is now named `Created`, and the previous `Created` state is now `Initialized`. The `podman ps` command already normalized these names for Docker compatibility, so this will only be visible when inspecting containers with `podman inspect`.
+
+### Changes
+- Podman containers will now automatically add the container's short ID as a network alias when connected to a supporting network ([#11748](https://github.com/containers/podman/issues/11748)).
+- The `podman machine stop` command will now log when machines are successfully stopped ([#11542](https://github.com/containers/podman/issues/11542)).
+- The `podman stop` command will now log a warning to the console if the stop timeout expires and `SIGKILL` must be used to stop the container ([#11854](https://github.com/containers/podman/issues/11854)).
+- Several performance optimizations have been implemented that should speed up container and pod creation, and running containers and pods that forward large ranges of ports.
+- The `--no-trunc` argument to the `podman search` command now defaults to true.
+- Rootless port forwarding using the `rootlessport` port forwarder is now handled by a separate binary, not Podman itself, which results in significantly reduced memory usage ([#10790](https://github.com/containers/podman/issues/10790)).
+- The `podman system connection ls` command now has a separate output column to show which connection is currently the default (instead appending `*` to the default connection's name) ([#12019](https://github.com/containers/podman/issues/12019)).
+- The `--kernel-memory` option to `podman run` and `podman create` has been deprecated in the upstream OCI runtime specification, and is now also deprecated in Podman and will be removed in a future release. Use of the flag will result in a warning.
+- Podman will now ship build the pause image used by pods locally, instead of pulling it from the network (using the existing `catatoinit` binary used for `podman run --init`). This allows pods to be easily used on systems without an internet connection.
+- The `--rootless-cni` option to `podman unshare` has been renamed to `--rootless-netns`. The old name has been aliased to the new one and will still function, but may be removed in a future release.
+- The `--cni-config-dir` option to all Podman commands has been renamed to `--network-config-dir` as it will not be used with Netavark as well as CNI. The old name has been aliased to the new one and will still function, but may be removed in a future release.
+- The `--format` option to all Podman commands has been changed to improved functionality and Docker compatibility ([#10974](https://github.com/containers/podman/issues/10974)).
+- The `podman ps --external` flag previously required `--all` to also be specified; this is no longer true
+- The `podman machine stop` command now waits until the VM has stopped to return; previously, it returned immediately after the shutdown command was sent, without waiting for the VM to shut down.
+- The port-forwarding logic previously contined in the `podman-machine-cni` CNI plugin has been integrated directly into Podman. The `podman-machine-cni` plugin is no longer necessary and should be removed.
+
+### Bugfixes
+- Fixed a bug where networks could be created with the same name as a container network mode (e.g. `host`) ([#11448](https://github.com/containers/podman/issues/11448)).
+- Fixed a bug where the `podman save` command was not automatically removing signatures from saved images.
+- Fixed a bug where a rare race condition could cause `podman run --rm` to return an error that a given container did not exist when trying to remove it, despite it having been safely removed ([#11775](https://github.com/containers/podman/issues/11775)).
+- Fixed a bug where a rare race condition could cause `podman ps` to return an error if a container was removed while the command was running ([#11810](https://github.com/containers/podman/issues/11810)).
+- Fixed a bug where running Kube YAML with a CPU limit would using `podman play kube` would result in errors ([#11803](https://github.com/containers/podman/issues/11803)).
+- Fixed a bug where creating a pod without an infra container would not generate an Pod Create event.
+- Fixed a bug where volumes created with the `:z` and `:Z` options would be relabelled every time a container was started, not just the first time.
+- Fixed a bug where the `podman tag` command on a manifest list could tag an image in the manifest, and not the manifest list itself.
+- Fixed a bug where creating a volume using an invalid volume option that contained a format string would print a nonsensical error.
+- Fixed a bug where Podman would not create a healthcheck for containers created from images that specified a healthcheck in their configuration ([#12226](https://github.com/containers/podman/issues/12226)).
+- Fixed a bug where rootless containers that used a custom user namespace (e.g. `--userns=keep-id`) could not have any ports forwarded to them.
+- Fixed a bug where the `podman system connection ls` command would not print any output (including headers) if no connections were present.
+- Fixed a bug where the `--memory-swappiness` option to `podman create` and `podman run` did not accept 0 as a valid value.
+- Fixed a bug where environment variables specified in `containers.conf` for Podman would sometimes not be applied ([#12296](https://github.com/containers/podman/issues/12296)).
+- Fixed a bug where running multiple rootless Podman instances with different configurations on the same system could cause networking issues due to the use of a single, shared rootless network namespace ([#12306](https://github.com/containers/podman/issues/12306)).
+- Fixed a bug where rootless containers using bridge networking would fail if `/etc/resolv.conf` was a symlink to a directory ([#12461](https://github.com/containers/podman/issues/12461)).
+- Fixed a bug where `podman container restore` could sometimes restore containers with a different OCI runtime than they had been using before they were checkpointed.
+- Fixed a bug where some commands of the remote Podman client allowed the `--signature-policy` option to be used (with no effect); `--signature-policy` is not supported by the remote client ([#12357](https://github.com/containers/podman/issues/12357)).
+- Fixed a bug where images which specified a port range in `EXPOSE` could not be run ([#12293](https://github.com/containers/podman/issues/12293)).
+- Fixed a bug where Podman would resolve image names without a tag to any tag of that image available on the local system, instead of the `:latest` tag ([#11964](https://github.com/containers/podman/issues/11964)).
+- Fixed a bug where the `--blkio-weight-device` option to `podman create` and `podman run` was nonfunctional.
+- Fixed a bug where the `podman generate systemd` command did not support container entrypoints that were specified as JSON arrays ([#12477](https://github.com/containers/podman/issues/12477)).
+- Fixed a bug where rootless Podman could, under some circumstances, exhaust all available inotify watches ([#11825](https://github.com/containers/podman/issues/11825)).
+- Fixed a bug where, when a container was created with both the `--hostname` and `--pod new:` options, the hostname would be discarded; it is now set as the hostname of the created pod, which will be used by the container.
+- Fixed a bug where the order in which `podman network ls` printed networks was not deterministic.
+- Fixed a bug where the `podman kill` command would sometimes not print the ID of containers that were killed.
+- Fixed a bug where VMs created by `podman machine` did not match their timezone to the host system ([#11895](https://github.com/containers/podman/issues/11895)).
+- Fixed a bug where container healthchecks were not properly cleaning up generated systemd services, leading to healthcheck failures after containers were restarted.
+- Fixed a bug where the `podman build` command did not properly propagate non-0 exit codes from Buildah when builds failed.
+- Fixed a bug where the remote Podman client's `--secret` option to the `podman build` command was nonfunctional.
+- Fixed a bug where the remote Podman client's `podman build` command would error if given a relative path to a Containerfile ([#12841](https://github.com/containers/podman/issues/12841)).
+- Fixed a bug where the `podman generate kube` command would sometimes omit environment variables set in containers from generated YAML.
+- Fixed a bug where setting `userns=auto` in `containers.conf` was not respected ([#12615](https://github.com/containers/podman/issues/12615)).
+- Fixed a bug where the `podman run` command would fail if the host machine did not have a `/etc/hosts` file ([#12667](https://github.com/containers/podman/issues/12667)).
+- Fixed a bug where certain annotations used internally by Podman could be set by images, resulting in `podman inspect` reporting incorrect information ([#12671](https://github.com/containers/podman/issues/12671)).
+- Fixed a bug where named volumes would not copy-up after being mounted over an empty directory, then subsequently mounted over a non-empty directory in another container ([#12714](https://github.com/containers/podman/issues/12714)).
+- Fixed a bug where the `podman inspect` command on containers was URL-encoding special characters in strings (e.g. healthcheck commands).
+- Fixed a bug where the `podman generate kube` command would generate YAML including optional environment variables from secrets and configmaps that are not included ([#12553](https://github.com/containers/podman/issues/12553)).
+- Fixed a bug where the `podman pod create` command would ignore the default infra image specified in `containers.conf` ([#12771](https://github.com/containers/podman/issues/12771)).
+- Fixed a bug where the `host.containers.internal` entry in `/etc/hosts` was set incorrectly to an inaccessible host IP for `macvlan` networks ([#11351](https://github.com/containers/podman/issues/11351)).
+- Fixed a bug where secrets could not be mounted into containers that joined a user namespace (e.g. `--userns=auto`) ([#12779](https://github.com/containers/podman/issues/12779)).
+- Fixed a bug where rootless Podman could produce an error about cgroups when containers were created inside existing pods ([#10800](https://github.com/containers/podman/issues/10800)).
+- Fixed a bug where Podman could error that a systemd session was not available despite having the cgroup manager set to `cgroupfs` ([#12802](https://github.com/containers/podman/issues/12802)).
+- Fixed a bug where the remote Podman client on Windows would ignore environment variables from the `--env` option to `podman create` and `podman run` ([#12056](https://github.com/containers/podman/issues/12056)).
+- Fixed a bug where Podman could segfault when an error occurred trying to set up rootless mode.
+- Fixed a bug where Podman could segfault when reading an image layer that did not have a creation timestamp set.
+
+### API
+- The Podman remote API version has been bumped to v4.0.0.
+- The Compat and Libpod Search endpoints for Images now will never truncate the returned image description. The `noTrunc` query parameter is now ignored as such ([#11894](https://github.com/containers/podman/issues/11894)).
+- The Libpod Top endpoints for Containers and Pods now support streaming output using the `stream=true` query parameter ([#12115](https://github.com/containers/podman/issues/12115)).
+- The Libpod Create endpoint for Volumes now supports specifying labels for the volume both as `Label` and `Labels` in the provided JSON configuration ([#12102](https://github.com/containers/podman/issues/12102)).
+- The Compat Create endpoint for Containers now respects cgroup configuration from `containers.conf` ([#12550](https://github.com/containers/podman/issues/12550)).
+- The Compat Create endpoint for Containers now respects user namespace configuration from the `PODMAN_USERNS` environment variable ([#11350](https://github.com/containers/podman/issues/11350)).
+- Fixed a bug where the Compat Create endpoint for Containers was ignoring the `HostConfig.StorageOpt` field ([#11016](https://github.com/containers/podman/issues/11016)).
+- Fixed a bug where the Compat List endpoint for Containers did not populate the `Mounts` field ([#12734](https://github.com/containers/podman/issues/12734)).
+- Fixed a bug where a race condition could cause a crash in the server when the Compat or Libpod Attach endpoints for Containers were invoked ([#12904](https://github.com/containers/podman/issues/12904)).
+- Fixed a bug where the Libpod Prune endpoint for Images would return nothing, instead of an empty array, when nothing was pruned.
+- Fixed a bug where the Compat List endpoint for Images did not prefix image IDs with `sha256:`.
+- Fixed a bug where the Compat Push endpoint for Images would return JSON which did not include the `size` field ([#12468](https://github.com/containers/podman/issues/12468)).
+- Fixed a bug where the Compat Load endpoint for Images would refuse to accept input archives that contained more than one image.
+- Fixed a bug where the Compat Build endpoint for Images ignored the `quiet` query parameter ([#12566](https://github.com/containers/podman/issues/12566)).
+- Fixed a bug where the Compat Build endpoint for Images did not include `aux` JSON (which included the ID of built images) in returned output ([#12063](https://github.com/containers/podman/issues/12063)).
+- Fixed a bug where the Compat and Libpod List endpoints for Networks would sometimes not return networks created on the server by the Podman CLI after the API server had been started ([#11828](https://github.com/containers/podman/issues/11828)).
+- Fixed a bug where the Compat Inspect endpoint for Networks did not include the subnet CIDR in the returned IPv4 and IPv6 addresses.
+- Fixed a bug where the Compat Events endpoint did not properly set the Action field of `Died` events for containers to `die` (previously, `died` was used; this was incompatible with Docker's output).
+- Fixed a bug where the Compat Info endpoint did not properly populate information on configured registries.
+- Fixed a bug where the Compat Events endpoint did not properly set the exit code of the container in the `exitCode` field in `Died` events for containers.
+- Fixed a bug where the Compat Events endpoint did not properly populate the `TimeNano` field.
+- Numerous small changes have been made to ensure that the API matches its Swagger documentation
+
+### Misc
+- The Windows installer MSI distributed through Github releases no longer supports 32-bit systems, as Podman is built only for 64-bit machines.
+
+## 3.4.4
+### Bugfixes
+- Fixed a bug where the `podman exec` command would, under some circumstances, print a warning message about failing to move `conmon` to the appropriate cgroup ([#12535](https://github.com/containers/podman/issues/12535)).
+- Fixed a bug where named volumes created as part of container creation (e.g. `podman run --volume avolume:/a/mountpoint` or similar) would be mounted with incorrect permissions ([#12523](https://github.com/containers/podman/issues/12523)).
+- Fixed a bug where the `podman-remote create` and `podman-remote run` commands did not properly handle the `--entrypoint=""` option (to clear the container's entrypoint) ([#12521](https://github.com/containers/podman/issues/12521)).
+
+## 3.4.3
+### Security
+- This release addresses CVE-2021-4024, where the `podman machine` command opened the `gvproxy` API (used to forward ports to `podman machine` VMs) to the public internet on port 7777.
+- This release addresses CVE-2021-41190, where incomplete specification of behavior regarding image manifests could lead to inconsistent decoding on different clients.
+
+### Features
+- The `--secret type=mount` option to `podman create` and `podman run` supports a new option, `target=`, which specifies where in the container the secret will be mounted ([#12287](https://github.com/containers/podman/issues/12287)).
+
+### Bugfixes
+- Fixed a bug where rootless Podman would occasionally print warning messages about failing to move the pause process to a new cgroup ([#12065](https://github.com/containers/podman/issues/12065)).
+- Fixed a bug where the `podman run` and `podman create` commands would, when pulling images, still require TLS even with registries set to Insecure via config file ([#11933](https://github.com/containers/podman/issues/11933)).
+- Fixed a bug where the `podman generate systemd` command generated units that depended on `multi-user.target`, which has been removed from some distributions ([#12438](https://github.com/containers/podman/issues/12438)).
+- Fixed a bug where Podman could not run containers with images that had `/etc/` as a symlink ([#12189](https://github.com/containers/podman/issues/12189)).
+- Fixed a bug where the `podman logs -f` command would, when using the `journald` logs backend, exit immediately if the container had previously been restarted ([#12263](https://github.com/containers/podman/issues/12263)).
+- Fixed a bug where, in containers on VMs created by `podman machine`, the `host.containers.internal` name pointed to the VM, not the host system ([#11642](https://github.com/containers/podman/issues/11642)).
+- Fixed a bug where containers and pods created by the `podman play kube` command in VMs managed by `podman machine` would not automatically forward ports from the host machine ([#12248](https://github.com/containers/podman/issues/12248)).
+- Fixed a bug where `podman machine init` would fail on OS X when GNU Coreutils was installed ([#12329](https://github.com/containers/podman/issues/12329)).
+- Fixed a bug where `podman machine start` would exit before SSH on the started VM was accepting connections ([#11532](https://github.com/containers/podman/issues/11532)).
+- Fixed a bug where the `podman run` command with signal proxying (`--sig-proxy`) enabled could print an error if it attempted to send a signal to a container that had just exited ([#8086](https://github.com/containers/podman/issues/8086)).
+- Fixed a bug where the `podman stats` command would not return correct information for containers running Systemd as PID1 ([#12400](https://github.com/containers/podman/issues/12400)).
+- Fixed a bug where the `podman image save` command would fail on OS X when writing the image to STDOUT ([#12402](https://github.com/containers/podman/issues/12402)).
+- Fixed a bug where the `podman ps` command did not properly handle PS arguments which contained whitespace ([#12452](https://github.com/containers/podman/issues/12452)).
+- Fixed a bug where the `podman-remote wait` command could fail to detect that the container exited and return an error under some circumstances ([#12457](https://github.com/containers/podman/issues/12457)).
+- Fixed a bug where the Windows MSI installer for `podman-remote` would break the PATH environment variable by adding an extra `"` ([#11416](https://github.com/containers/podman/issues/11416)).
+
+### API
+- Updated the containers/image library to v5.17.0
+- The Libpod Play Kube endpoint now also accepts `ConfigMap` YAML as part of its payload, and will use provided any `ConfigMap` to configure provided pods and services.
+- Fixed a bug where the Compat Create endpoint for Containers would not always create the container's working directory if it did not exist ([#11842](https://github.com/containers/podman/issues/11842)).
+- Fixed a bug where the Compat Create endpoint for Containers returned an incorrect error message with 404 errors when the requested image was not found ([#12315](https://github.com/containers/podman/pull/12315)).
+- Fixed a bug where the Compat Create endpoint for Containers did not properly handle the `HostConfig.Mounts` field ([#12419](https://github.com/containers/podman/issues/12419)).
+- Fixed a bug where the Compat Archive endpoint for Containers did not properly report errors when the operation failed ([#12420](https://github.com/containers/podman/issues/12420)).
+- Fixed a bug where the Compat Build endpoint for Images ignored the `layers` query parameter (for caching intermediate layers from the build) ([#12378](https://github.com/containers/podman/issues/12378)).
+- Fixed a bug where the Compat Build endpoint for Images did not report errors in a manner compatible with Docker ([#12392](https://github.com/containers/podman/issues/12392)).
+- Fixed a bug where the Compat Build endpoint for Images would fail to build if the context directory was a symlink ([#12409](https://github.com/containers/podman/issues/12409)).
+- Fixed a bug where the Compat List endpoint for Images included manifest lists (and not just images) in returned results ([#12453](https://github.com/containers/podman/issues/12453)).
+
+### Misc
+- Updated the containers/image library to v5.17.0
+- Updated the containers/storage library to v1.37.0
+- Podman now builds by default with cgo enabled on OS X, resolving some issues with SSH ([#10737](https://github.com/containers/podman/issues/10737)).
+
+## 3.4.2
+### Bugfixes
+- Fixed a bug where `podman tag` could not tag manifest lists ([#12046](https://github.com/containers/podman/issues/12046)).
+- Fixed a bug where built-in volumes specified by images would not be created correctly under some circumstances.
+- Fixed a bug where, when using Podman Machine on OS X, containers in pods did not have working port forwarding from the host ([#12207](https://github.com/containers/podman/issues/12207)).
+- Fixed a bug where the `podman network reload` command command on containers using the `slirp4netns` network mode and the `rootlessport` port forwarding driver would make an unnecessary attempt to restart `rootlessport` on containers that did not forward ports.
+- Fixed a bug where the `podman generate kube` command would generate YAML including some unnecessary (set to default) fields (e.g. empty SELinux and DNS configuration blocks, and the `privileged` flag when set to false) ([#11995](https://github.com/containers/podman/issues/11995)).
+- Fixed a bug where the `podman pod rm` command could, if interrupted at the right moment, leave a reference to an already-removed infra container behind ([#12034](https://github.com/containers/podman/issues/12034)).
+- Fixed a bug where the `podman pod rm` command would not remove pods with more than one container if all containers save for the infra container were stopped unless `--force` was specified ([#11713](https://github.com/containers/podman/issues/11713)).
+- Fixed a bug where the `--memory` flag to `podman run` and `podman create` did not accept a limit of 0 (which should specify unlimited memory) ([#12002](https://github.com/containers/podman/issues/12002)).
+- Fixed a bug where the remote Podman client's `podman build` command could attempt to build a Dockerfile in the working directory of the `podman system service` instance instead of the Dockerfile specified by the user ([#12054](https://github.com/containers/podman/issues/12054)).
+- Fixed a bug where the `podman logs --tail` command could function improperly (printing more output than requested) when the `journald` log driver was used.
+- Fixed a bug where containers run using the `slirp4netns` network mode with IPv6 enabled would not have IPv6 connectivity until several seconds after they started ([#11062](https://github.com/containers/podman/issues/11062)).
+- Fixed a bug where some Podman commands could cause an extra `dbus-daemon` process to be created ([#9727](https://github.com/containers/podman/issues/9727)).
+- Fixed a bug where rootless Podman would sometimes print warnings about a failure to move the pause process into a given CGroup ([#12065](https://github.com/containers/podman/issues/12065)).
+- Fixed a bug where the `checkpointed` field in `podman inspect` on a container was not set to false after a container was restored.
+- Fixed a bug where the `podman system service` command would print overly-verbose logs about request IDs ([#12181](https://github.com/containers/podman/issues/12181)).
+- Fixed a bug where Podman could, when creating a new container without a name explicitly specified by the user, sometimes use an auto-generated name already in use by another container if multiple containers were being created in parallel ([#11735](https://github.com/containers/podman/issues/11735)).
+
+## 3.4.1
+### Bugfixes
+- Fixed a bug where `podman machine init` could, under some circumstances, create invalid machine configurations which could not be started ([#11824](https://github.com/containers/podman/issues/11824)).
+- Fixed a bug where the `podman machine list` command would not properly populate some output fields.
+- Fixed a bug where `podman machine rm` could leave dangling sockets from the removed machine ([#11393](https://github.com/containers/podman/issues/11393)).
+- Fixed a bug where `podman run --pids-limit=-1` was not supported (it now sets the PID limit in the container to unlimited) ([#11782](https://github.com/containers/podman/issues/11782)).
+- Fixed a bug where `podman run` and `podman attach` could throw errors about a closed network connection when STDIN was closed by the client ([#11856](https://github.com/containers/podman/issues/11856)).
+- Fixed a bug where the `podman stop` command could fail when run on a container that had another `podman stop` command run on it previously.
+- Fixed a bug where the `--sync` flag to `podman ps` was nonfunctional.
+- Fixed a bug where the Windows and OS X remote clients' `podman stats` command would fail ([#11909](https://github.com/containers/podman/issues/11909)).
+- Fixed a bug where the `podman play kube` command did not properly handle environment variables whose values contained an `=` ([#11891](https://github.com/containers/podman/issues/11891)).
+- Fixed a bug where the `podman generate kube` command could generate invalid annotations when run on containers with volumes that use SELinux relabelling (`:z` or `:Z`) ([#11929](https://github.com/containers/podman/issues/11929)).
+- Fixed a bug where the `podman generate kube` command would generate YAML including some unnecessary (set to default) fields (e.g. user and group, entrypoint, default protocol for forwarded ports) ([#11914](https://github.com/containers/podman/issues/11914), [#11915](https://github.com/containers/podman/issues/11915), and [#11965](https://github.com/containers/podman/issues/11965)).
+- Fixed a bug where the `podman generate kube` command could, under some circumstances, generate YAML including an invalid `targetPort` field for forwarded ports ([#11930](https://github.com/containers/podman/issues/11930)).
+- Fixed a bug where rootless Podman's `podman info` command could, under some circumstances, not read available CGroup controllers ([#11931](https://github.com/containers/podman/issues/11931)).
+- Fixed a bug where `podman container checkpoint --export` would fail to checkpoint any container created with `--log-driver=none` ([#11974](https://github.com/containers/podman/issues/11974)).
+
+### API
+- Fixed a bug where the Compat Create endpoint for Containers could panic when no options were passed to a bind mount of tmpfs ([#11961](https://github.com/containers/podman/issues/11961)).
+
## 3.4.0
### Features
- Pods now support init containers! Init containers are containers which run before the rest of the pod starts. There are two types of init containers: "always", which always run before the pod is started, and "once", which only run the first time the pod starts and are subsequently removed. They can be added using the `podman create` command's `--init-ctr` option.
diff --git a/SECURITY.md b/SECURITY.md
index 1f6d5088d..6f919afbb 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,3 +1,3 @@
-## Security and Disclosure Information Policy for the Libpod Project
+## Security and Disclosure Information Policy for the Podman Project
-The Libpod Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects.
+The Podman Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects.
diff --git a/build_osx.md b/build_osx.md
index 631fcf9c3..8b2341cbb 100644
--- a/build_osx.md
+++ b/build_osx.md
@@ -28,7 +28,7 @@ can now be built.
```
$ cd go/src/github.com/containers/podman
$ make podman-remote-darwin
-$ mv bin/podman-remote-darwin bin/podman
+$ mv bin/darwin/podman bin/podman
```
The binary will be located in bin/
diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go
index 255996ac3..9dfe81d62 100644
--- a/cmd/podman/common/netflags.go
+++ b/cmd/podman/common/netflags.go
@@ -103,69 +103,79 @@ func NetFlagsToNetOptions(opts *entities.NetOptions, flags pflag.FlagSet) (*enti
opts = &entities.NetOptions{}
}
- opts.AddHosts, err = flags.GetStringSlice("add-host")
- if err != nil {
- return nil, err
- }
- // Verify the additional hosts are in correct format
- for _, host := range opts.AddHosts {
- if _, err := parse.ValidateExtraHost(host); err != nil {
+ if flags.Changed("add-host") {
+ opts.AddHosts, err = flags.GetStringSlice("add-host")
+ if err != nil {
return nil, err
}
+ // Verify the additional hosts are in correct format
+ for _, host := range opts.AddHosts {
+ if _, err := parse.ValidateExtraHost(host); err != nil {
+ return nil, err
+ }
+ }
}
- servers, err := flags.GetStringSlice("dns")
- if err != nil {
- return nil, err
- }
- for _, d := range servers {
- if d == "none" {
- opts.UseImageResolvConf = true
- if len(servers) > 1 {
- return nil, errors.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
- }
- break
+ if flags.Changed("dns") {
+ servers, err := flags.GetStringSlice("dns")
+ if err != nil {
+ return nil, err
}
- dns := net.ParseIP(d)
- if dns == nil {
- return nil, errors.Errorf("%s is not an ip address", d)
+ for _, d := range servers {
+ if d == "none" {
+ opts.UseImageResolvConf = true
+ if len(servers) > 1 {
+ return nil, errors.Errorf("%s is not allowed to be specified with other DNS ip addresses", d)
+ }
+ break
+ }
+ dns := net.ParseIP(d)
+ if dns == nil {
+ return nil, errors.Errorf("%s is not an ip address", d)
+ }
+ opts.DNSServers = append(opts.DNSServers, dns)
}
- opts.DNSServers = append(opts.DNSServers, dns)
}
- options, err := flags.GetStringSlice("dns-opt")
- if err != nil {
- return nil, err
+ if flags.Changed("dns-opt") {
+ options, err := flags.GetStringSlice("dns-opt")
+ if err != nil {
+ return nil, err
+ }
+ opts.DNSOptions = options
}
- opts.DNSOptions = options
- dnsSearches, err := flags.GetStringSlice("dns-search")
- if err != nil {
- return nil, err
- }
- // Validate domains are good
- for _, dom := range dnsSearches {
- if dom == "." {
- if len(dnsSearches) > 1 {
- return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
- }
- continue
- }
- if _, err := parse.ValidateDomain(dom); err != nil {
+ if flags.Changed("dns-search") {
+ dnsSearches, err := flags.GetStringSlice("dns-search")
+ if err != nil {
return nil, err
}
+ // Validate domains are good
+ for _, dom := range dnsSearches {
+ if dom == "." {
+ if len(dnsSearches) > 1 {
+ return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
+ }
+ continue
+ }
+ if _, err := parse.ValidateDomain(dom); err != nil {
+ return nil, err
+ }
+ }
+ opts.DNSSearch = dnsSearches
}
- opts.DNSSearch = dnsSearches
- inputPorts, err := flags.GetStringSlice("publish")
- if err != nil {
- return nil, err
- }
- if len(inputPorts) > 0 {
- opts.PublishPorts, err = specgenutil.CreatePortBindings(inputPorts)
+ if flags.Changed("publish") {
+ inputPorts, err := flags.GetStringSlice("publish")
if err != nil {
return nil, err
}
+ if len(inputPorts) > 0 {
+ opts.PublishPorts, err = specgenutil.CreatePortBindings(inputPorts)
+ if err != nil {
+ return nil, err
+ }
+ }
}
opts.NoHosts, err = flags.GetBool("no-hosts")
diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go
index 5ad42ebc0..0dab6299d 100644
--- a/cmd/podman/generate/systemd.go
+++ b/cmd/podman/generate/systemd.go
@@ -25,6 +25,9 @@ const (
restartPolicyFlagName = "restart-policy"
restartSecFlagName = "restart-sec"
newFlagName = "new"
+ wantsFlagName = "wants"
+ afterFlagName = "after"
+ requiresFlagName = "requires"
)
var (
@@ -97,6 +100,15 @@ func init() {
flags.StringVar(&format, formatFlagName, "", "Print the created units in specified format (json)")
_ = systemdCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(nil))
+ flags.StringArrayVar(&systemdOptions.Wants, wantsFlagName, nil, "Add (weak) requirement dependencies to the generated unit file")
+ _ = systemdCmd.RegisterFlagCompletionFunc(wantsFlagName, completion.AutocompleteNone)
+
+ flags.StringArrayVar(&systemdOptions.After, afterFlagName, nil, "Add dependencies order to the generated unit file")
+ _ = systemdCmd.RegisterFlagCompletionFunc(afterFlagName, completion.AutocompleteNone)
+
+ flags.StringArrayVar(&systemdOptions.Requires, requiresFlagName, nil, "Similar to wants, but declares stronger requirement dependencies")
+ _ = systemdCmd.RegisterFlagCompletionFunc(requiresFlagName, completion.AutocompleteNone)
+
flags.SetNormalizeFunc(utils.TimeoutAliasFlags)
}
diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go
index f975cd6d5..729951a31 100644
--- a/cmd/podman/images/build.go
+++ b/cmd/podman/images/build.go
@@ -183,12 +183,6 @@ func buildFlags(cmd *cobra.Command) {
completion.CompleteCommandFlags(cmd, fromAndBudFlagsCompletions)
flags.SetNormalizeFunc(buildahCLI.AliasFlags)
if registry.IsRemote() {
- flag = flags.Lookup("isolation")
- buildOpts.Isolation = buildahDefine.OCI
- if err := flag.Value.Set(buildahDefine.OCI); err != nil {
- logrus.Errorf("Unable to set --isolation to %v: %v", buildahDefine.OCI, err)
- }
- flag.DefValue = buildahDefine.OCI
_ = flags.MarkHidden("disable-content-trust")
_ = flags.MarkHidden("cache-from")
_ = flags.MarkHidden("sign-by")
@@ -360,15 +354,18 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil
return nil, errors.Errorf("can only set one of 'pull' or 'pull-always' or 'pull-never'")
}
+ // Allow for --pull, --pull=true, --pull=false, --pull=never, --pull=always
+ // --pull-always and --pull-never. The --pull-never and --pull-always options
+ // will not be documented.
pullPolicy := buildahDefine.PullIfMissing
- if c.Flags().Changed("pull") && flags.Pull {
+ if c.Flags().Changed("pull") && strings.EqualFold(strings.TrimSpace(flags.Pull), "true") {
pullPolicy = buildahDefine.PullAlways
}
- if flags.PullAlways {
+ if flags.PullAlways || strings.EqualFold(strings.TrimSpace(flags.Pull), "always") {
pullPolicy = buildahDefine.PullAlways
}
- if flags.PullNever {
+ if flags.PullNever || strings.EqualFold(strings.TrimSpace(flags.Pull), "never") {
pullPolicy = buildahDefine.PullNever
}
diff --git a/cmd/podman/images/scp.go b/cmd/podman/images/scp.go
index 1481e71c7..d07a5d99d 100644
--- a/cmd/podman/images/scp.go
+++ b/cmd/podman/images/scp.go
@@ -17,7 +17,6 @@ import (
"github.com/containers/podman/v4/cmd/podman/system/connection"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/utils"
scpD "github.com/dtylman/scp"
"github.com/pkg/errors"
@@ -147,6 +146,17 @@ func scp(cmd *cobra.Command, args []string) (finalErr error) {
return err
}
+ allLocal := true // if we are all localhost, do not validate connections but if we are using one localhost and one non we need to use sshd
+ for _, val := range cliConnections {
+ if !strings.Contains(val, "@localhost::") {
+ allLocal = false
+ break
+ }
+ }
+ if allLocal {
+ cliConnections = []string{}
+ }
+
var serv map[string]config.Destination
serv, err = GetServiceInformation(cliConnections, cfg)
if err != nil {
@@ -337,21 +347,9 @@ func GetServiceInformation(cliConnections []string, cfg *config.Config) (map[str
// execPodman executes the podman save/load command given the podman binary
func execPodman(podman string, command []string) error {
- if rootless.IsRootless() {
- cmd := exec.Command(podman)
- utils.CreateSCPCommand(cmd, command[1:])
- logrus.Debug("Executing podman command")
- return cmd.Run()
- }
- machinectl, err := exec.LookPath("machinectl")
- if err != nil {
- cmd := exec.Command("su", "-l", "root", "--command")
- cmd = utils.CreateSCPCommand(cmd, []string{strings.Join(command, " ")})
- return cmd.Run()
- }
- cmd := exec.Command(machinectl, "shell", "-q", "root@.host")
- cmd = utils.CreateSCPCommand(cmd, command)
- logrus.Debug("Executing load command machinectl")
+ cmd := exec.Command(podman)
+ utils.CreateSCPCommand(cmd, command[1:])
+ logrus.Debugf("Executing podman command: %q", cmd)
return cmd.Run()
}
diff --git a/cmd/podman/images/scp_utils.go b/cmd/podman/images/scp_utils.go
index c488616c9..a85687a42 100644
--- a/cmd/podman/images/scp_utils.go
+++ b/cmd/podman/images/scp_utils.go
@@ -17,12 +17,13 @@ func parseImageSCPArg(arg string) (*entities.ImageScpOptions, []string, error) {
cliConnections := []string{}
switch {
- case strings.Contains(arg, "@localhost"): // image transfer between users
+ case strings.Contains(arg, "@localhost::"): // image transfer between users
location.User = strings.Split(arg, "@")[0]
location, err = validateImagePortion(location, arg)
if err != nil {
return nil, nil, err
}
+ cliConnections = append(cliConnections, arg)
case strings.Contains(arg, "::"):
location, err = validateImagePortion(location, arg)
if err != nil {
diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go
index 0bcf32cd5..16faa25ef 100644
--- a/cmd/podman/machine/start.go
+++ b/cmd/podman/machine/start.go
@@ -1,3 +1,4 @@
+//go:build amd64 || arm64
// +build amd64 arm64
package machine
@@ -64,5 +65,6 @@ func start(cmd *cobra.Command, args []string) error {
if err := vm.Start(vmName, machine.StartOptions{}); err != nil {
return err
}
+ fmt.Printf("Machine %q started successfully\n", vmName)
return nil
}
diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go
index 9f6470858..3dd393c46 100644
--- a/cmd/podman/networks/create.go
+++ b/cmd/podman/networks/create.go
@@ -47,13 +47,13 @@ func networkCreateFlags(cmd *cobra.Command) {
_ = cmd.RegisterFlagCompletionFunc(optFlagName, completion.AutocompleteNone)
gatewayFlagName := "gateway"
- flags.IPVar(&networkCreateOptions.Gateway, gatewayFlagName, nil, "IPv4 or IPv6 gateway for the subnet")
+ flags.IPSliceVar(&networkCreateOptions.Gateways, gatewayFlagName, nil, "IPv4 or IPv6 gateway for the subnet")
_ = cmd.RegisterFlagCompletionFunc(gatewayFlagName, completion.AutocompleteNone)
flags.BoolVar(&networkCreateOptions.Internal, "internal", false, "restrict external access from this network")
ipRangeFlagName := "ip-range"
- flags.IPNetVar(&networkCreateOptions.Range, ipRangeFlagName, net.IPNet{}, "allocate container IP from range")
+ flags.StringArrayVar(&networkCreateOptions.Ranges, ipRangeFlagName, nil, "allocate container IP from range")
_ = cmd.RegisterFlagCompletionFunc(ipRangeFlagName, completion.AutocompleteNone)
// TODO consider removing this for 4.0
@@ -72,7 +72,7 @@ func networkCreateFlags(cmd *cobra.Command) {
flags.BoolVar(&networkCreateOptions.IPv6, "ipv6", false, "enable IPv6 networking")
subnetFlagName := "subnet"
- flags.IPNetVar(&networkCreateOptions.Subnet, subnetFlagName, net.IPNet{}, "subnet in CIDR format")
+ flags.StringArrayVar(&networkCreateOptions.Subnets, subnetFlagName, nil, "subnets in CIDR format")
_ = cmd.RegisterFlagCompletionFunc(subnetFlagName, completion.AutocompleteNone)
flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")
@@ -125,27 +125,35 @@ func networkCreate(cmd *cobra.Command, args []string) error {
}
}
- if networkCreateOptions.Subnet.IP != nil {
- s := types.Subnet{
- Subnet: types.IPNet{IPNet: networkCreateOptions.Subnet},
- Gateway: networkCreateOptions.Gateway,
+ if len(networkCreateOptions.Subnets) > 0 {
+ if len(networkCreateOptions.Gateways) > len(networkCreateOptions.Subnets) {
+ return errors.New("cannot set more gateways than subnets")
}
- if networkCreateOptions.Range.IP != nil {
- startIP, err := util.FirstIPInSubnet(&networkCreateOptions.Range)
+ if len(networkCreateOptions.Ranges) > len(networkCreateOptions.Subnets) {
+ return errors.New("cannot set more ranges than subnets")
+ }
+
+ for i := range networkCreateOptions.Subnets {
+ subnet, err := types.ParseCIDR(networkCreateOptions.Subnets[i])
if err != nil {
- return errors.Wrap(err, "failed to get first ip in range")
+ return err
}
- lastIP, err := util.LastIPInSubnet(&networkCreateOptions.Range)
- if err != nil {
- return errors.Wrap(err, "failed to get last ip in range")
+ s := types.Subnet{
+ Subnet: subnet,
+ }
+ if len(networkCreateOptions.Ranges) > i {
+ leaseRange, err := parseRange(networkCreateOptions.Ranges[i])
+ if err != nil {
+ return err
+ }
+ s.LeaseRange = leaseRange
}
- s.LeaseRange = &types.LeaseRange{
- StartIP: startIP,
- EndIP: lastIP,
+ if len(networkCreateOptions.Gateways) > i {
+ s.Gateway = networkCreateOptions.Gateways[i]
}
+ network.Subnets = append(network.Subnets, s)
}
- network.Subnets = append(network.Subnets, s)
- } else if networkCreateOptions.Range.IP != nil || networkCreateOptions.Gateway != nil {
+ } else if len(networkCreateOptions.Ranges) > 0 || len(networkCreateOptions.Gateways) > 0 {
return errors.New("cannot set gateway or range without subnet")
}
@@ -156,3 +164,23 @@ func networkCreate(cmd *cobra.Command, args []string) error {
fmt.Println(response.Name)
return nil
}
+
+func parseRange(iprange string) (*types.LeaseRange, error) {
+ _, subnet, err := net.ParseCIDR(iprange)
+ if err != nil {
+ return nil, err
+ }
+
+ startIP, err := util.FirstIPInSubnet(subnet)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to get first ip in range")
+ }
+ lastIP, err := util.LastIPInSubnet(subnet)
+ if err != nil {
+ return nil, errors.Wrap(err, "failed to get last ip in range")
+ }
+ return &types.LeaseRange{
+ StartIP: startIP,
+ EndIP: lastIP,
+ }, nil
+}
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 092cc6424..f14e0ed0f 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -71,7 +71,6 @@ func networkList(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
-
// sort the networks to make sure the order is deterministic
sort.Slice(responses, func(i, j int) bool {
return responses[i].Name < responses[j].Name
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 8222ec8e2..1cd36008e 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -77,7 +77,7 @@ func init() {
if !registry.IsRemote() {
defInfraImage = containerConfig.Engine.InfraImage
}
- flags.StringVar(&infraImage, infraImageFlagName, defInfraImage, "The image of the infra container to associate with the pod")
+ flags.StringVar(&infraImage, infraImageFlagName, defInfraImage, "Image to use to override builtin infra container")
_ = createCommand.RegisterFlagCompletionFunc(infraImageFlagName, common.AutocompleteImages)
podIDFileFlagName := "pod-id-file"
diff --git a/cmd/podman/registry/config.go b/cmd/podman/registry/config.go
index f5822d33e..15bb7aee0 100644
--- a/cmd/podman/registry/config.go
+++ b/cmd/podman/registry/config.go
@@ -52,6 +52,12 @@ func newPodmanConfig() {
os.Exit(1)
}
+ cfg, err := config.NewConfig("")
+ if err != nil {
+ fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error())
+ os.Exit(1)
+ }
+
var mode entities.EngineMode
switch runtime.GOOS {
case "darwin", "windows":
@@ -64,16 +70,15 @@ func newPodmanConfig() {
} else {
mode = entities.TunnelMode
}
-
default:
fmt.Fprintf(os.Stderr, "%s is not a supported OS", runtime.GOOS)
os.Exit(1)
}
- cfg, err := config.NewConfig("")
- if err != nil {
- fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error())
- os.Exit(1)
+ // If EngineMode==Tunnel has not been set on the command line or environment
+ // but has been set in containers.conf...
+ if mode == entities.ABIMode && cfg.Engine.Remote {
+ mode = entities.TunnelMode
}
cfg.Network.NetworkConfigDir = cfg.Network.CNIPluginDirs[0]
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 7989f9cd5..6d768c2e6 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -85,6 +85,14 @@ func init() {
)
rootFlags(rootCmd, registry.PodmanConfig())
+
+ // backwards compat still allow --cni-config-dir
+ rootCmd.Flags().SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ if name == "cni-config-dir" {
+ name = "network-config-dir"
+ }
+ return pflag.NormalizedName(name)
+ })
rootCmd.SetUsageTemplate(usageTemplate)
}
@@ -371,9 +379,9 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
pFlags.StringVar(&cfg.Engine.NetworkCmdPath, networkCmdPathFlagName, cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network")
_ = cmd.RegisterFlagCompletionFunc(networkCmdPathFlagName, completion.AutocompleteDefault)
- cniConfigDirFlagName := "cni-config-dir"
- pFlags.StringVar(&cfg.Network.NetworkConfigDir, cniConfigDirFlagName, cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks")
- _ = cmd.RegisterFlagCompletionFunc(cniConfigDirFlagName, completion.AutocompleteDefault)
+ networkConfigDirFlagName := "network-config-dir"
+ pFlags.StringVar(&cfg.Network.NetworkConfigDir, networkConfigDirFlagName, cfg.Network.NetworkConfigDir, "Path of the configuration directory for networks")
+ _ = cmd.RegisterFlagCompletionFunc(networkConfigDirFlagName, completion.AutocompleteDefault)
pFlags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file")
@@ -407,12 +415,12 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
_ = cmd.RegisterFlagCompletionFunc(runrootFlagName, completion.AutocompleteDefault)
runtimeFlagName := "runtime"
- pFlags.StringVar(&opts.RuntimePath, runtimeFlagName, "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
+ pFlags.StringVar(&opts.RuntimePath, runtimeFlagName, cfg.Engine.OCIRuntime, "Path to the OCI-compatible binary used to run containers.")
_ = cmd.RegisterFlagCompletionFunc(runtimeFlagName, completion.AutocompleteDefault)
// -s is deprecated due to conflict with -s on subcommands
storageDriverFlagName := "storage-driver"
- pFlags.StringVar(&opts.StorageDriver, storageDriverFlagName, "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
+ pFlags.StringVar(&opts.StorageDriver, storageDriverFlagName, "", "Select which storage driver is used to manage storage of images and containers")
_ = cmd.RegisterFlagCompletionFunc(storageDriverFlagName, completion.AutocompleteNone) //TODO: what can we recommend here?
tmpdirFlagName := "tmpdir"
diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go
index 85ee8557a..07904faaa 100644
--- a/cmd/podman/system/reset.go
+++ b/cmd/podman/system/reset.go
@@ -21,7 +21,7 @@ import (
var (
systemResetDescription = `Reset podman storage back to default state"
- All containers will be stopped and removed, and all images, volumes and container content will be removed.
+ All containers will be stopped and removed, and all images, volumes, networks and container content will be removed.
`
systemResetCommand = &cobra.Command{
Annotations: map[string]string{registry.EngineMode: registry.ABIMode},
@@ -55,11 +55,11 @@ func reset(cmd *cobra.Command, args []string) {
// Prompt for confirmation if --force is not set
if !forceFlag {
reader := bufio.NewReader(os.Stdin)
- fmt.Println(`
-WARNING! This will remove:
+ fmt.Println(`WARNING! This will remove:
- all containers
- all pods
- all images
+ - all networks
- all build cache`)
if len(listCtn) > 0 {
fmt.Println(`WARNING! The following external containers will be purged:`)
diff --git a/contrib/build_rpm.sh b/contrib/build_rpm.sh
deleted file mode 100755
index 3039c1bf9..000000000
--- a/contrib/build_rpm.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env bash
-set -euxo pipefail
-
-# returned path can vary: /usr/bin/dnf /bin/dnf ...
-pkg_manager=$(command -v dnf yum | head -n1)
-echo "Package manager binary: $pkg_manager"
-
-
-if [[ $pkg_manager == *yum ]]; then
- echo "[virt7-container]
-name=virt7-container
-baseurl=https://buildlogs.centos.org/centos/7/virt/x86_64/container/
-enabled=1
-gpgcheck=0" > /etc/yum.repos.d/container_virt.repo
- echo "[paas_openshift_origin311]
-name=paas_openshift_origin311
-# Use this if you need the newest *-testing packages
-# baseurl=https://buildlogs.centos.org/centos/7/paas/x86_64/openshift-origin311/
-baseurl=http://mirror.centos.org/centos/7/paas/x86_64/openshift-origin311/
-enabled=1
-gpgcheck=0" > /etc/yum.repos.d/paas_openshift_origin311.repo
-fi
-
-declare -a PKGS=(\
- createrepo \
- device-mapper-devel \
- git \
- glib2-devel \
- glibc-static \
- go-compilers-golang-compiler \
- golang \
- gpgme-devel \
- libassuan-devel \
- libseccomp-devel \
- libselinux-devel \
- make \
- redhat-rpm-config \
- rpm-build \
- rpmdevtools \
- systemd-devel \
- )
-
-if [[ $pkg_manager == *dnf ]]; then
- # We need to enable PowerTools if we want to get
- # install all the pkgs we define in PKGS
- # PowerTools exists on centos-8 but not on fedora-30 and rhel-8
- if (dnf -v -C repolist all|grep "Repo-id : PowerTools" >/dev/null); then
- sudo dnf config-manager --set-enabled PowerTools
- fi
-
- PKGS+=(python3-devel \
- )
-fi
-
-# 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
-
-# disable doc until go-md2man rpm becomes available
-# disable debug to avoid error: Empty %files file ~/rpmbuild/BUILD/libpod-.../debugsourcefiles.list
-export extra_arg="--without doc --without debug"
-
-echo ${PKGS[*]}
-sudo $pkg_manager install -y ${PKGS[*]}
-
-# clean up src.rpm as it's been built
-sudo rm -f podman-*.src.rpm
-
-make -f .copr/Makefile
-# workaround for https://github.com/containers/podman/issues/4627
-if [ -d ~/rpmbuild/BUILD ]; then
- chmod -R +w ~/rpmbuild/BUILD
-fi
-
-rpmbuild --rebuild ${extra_arg:-} podman-*.src.rpm
diff --git a/contrib/cirrus/cron-fail_addrs.csv b/contrib/cirrus/cron-fail_addrs.csv
deleted file mode 100644
index 276158163..000000000
--- a/contrib/cirrus/cron-fail_addrs.csv
+++ /dev/null
@@ -1 +0,0 @@
-rh.container.bot@gmail.com,podman-monitor@lists.podman.io
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index c7352106a..09a255e6f 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -138,7 +138,9 @@ passthrough_envars(){
}
setup_rootless() {
- req_env_vars ROOTLESS_USER GOPATH GOSRC SECRET_ENV_RE
+ req_env_vars GOPATH GOSRC SECRET_ENV_RE
+
+ ROOTLESS_USER="${ROOTLESS_USER:-some${RANDOM}dude}"
local rootless_uid
local rootless_gid
@@ -150,9 +152,11 @@ setup_rootless() {
# shellcheck disable=SC2154
if passwd --status $ROOTLESS_USER
then
- msg "Updating $ROOTLESS_USER user permissions on possibly changed libpod code"
- chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
- return 0
+ if [[ $PRIV_NAME = "rootless" ]]; then
+ msg "Updating $ROOTLESS_USER user permissions on possibly changed libpod code"
+ chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
+ return 0
+ fi
fi
msg "************************************************************"
msg "Setting up rootless user '$ROOTLESS_USER'"
@@ -164,7 +168,11 @@ setup_rootless() {
msg "creating $rootless_uid:$rootless_gid $ROOTLESS_USER user"
groupadd -g $rootless_gid $ROOTLESS_USER
useradd -g $rootless_gid -u $rootless_uid --no-user-group --create-home $ROOTLESS_USER
- chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
+
+ # We also set up rootless user for image-scp tests (running as root)
+ if [[ $PRIV_NAME = "rootless" ]]; then
+ chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
+ fi
echo "$ROOTLESS_USER ALL=(root) NOPASSWD: ALL" > /etc/sudoers.d/ci-rootless
mkdir -p "$HOME/.ssh" "/home/$ROOTLESS_USER/.ssh"
@@ -206,16 +214,22 @@ setup_rootless() {
}
install_test_configs() {
- echo "Installing cni config, policy and registry config"
- req_env_vars GOSRC SCRIPT_BASE
- cd $GOSRC || exit 1
- install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
- # This config must always sort last in the list of networks (podman picks first one
- # as the default). This config prevents allocation of network address space used
- # by default in google cloud. https://cloud.google.com/vpc/docs/vpc#ip-ranges
- install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/
-
+ msg "Installing ./test/registries.conf system-wide."
install -v -D -m 644 ./test/registries.conf /etc/containers/
+ if [[ "$TEST_ENVIRON" =~ netavark ]]; then
+ # belt-and-suspenders: any pre-existing CNI config. will spoil
+ # default use tof netavark (when both are installed).
+ rm -rf /etc/cni/net.d/*
+ else
+ echo "Installing cni config, policy and registry config"
+ req_env_vars GOSRC SCRIPT_BASE
+ cd $GOSRC || exit 1
+ install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
+ # This config must always sort last in the list of networks (podman picks first one
+ # as the default). This config prevents allocation of network address space used
+ # by default in google cloud. https://cloud.google.com/vpc/docs/vpc#ip-ranges
+ install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/
+ fi
}
# Remove all files provided by the distro version of podman.
diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh
index 38a15ded1..0cfbf7135 100755
--- a/contrib/cirrus/logcollector.sh
+++ b/contrib/cirrus/logcollector.sh
@@ -74,6 +74,19 @@ case $1 in
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
+
+ # TODO: Remove this once netavark/aardvark-dns packages are used
+ if [[ "$TEST_ENVIRON" =~ netavark ]]; then
+ _npath=/usr/local/libexec/podman/
+ for name in netavark aardvark-dns; do
+ echo "$name binary details:"
+ if [[ -r "$_npath/${name}.info" ]]; then
+ cat "$_npath/${name}.info"
+ else
+ echo "WARNING: $_npath/${name}.info not found."
+ fi
+ done
+ fi
;;
time)
# Assumed to be empty/undefined outside of Cirrus-CI (.cirrus.yml)
diff --git a/contrib/cirrus/logformatter b/contrib/cirrus/logformatter
index 70f119b5b..49ca91399 100755
--- a/contrib/cirrus/logformatter
+++ b/contrib/cirrus/logformatter
@@ -341,7 +341,7 @@ END_HTML
# Highlight the important (non-boilerplate) podman command.
$line =~ s/\s+--remote\s+/ /g; # --remote takes no args
# Strip out the global podman options, but show them on hover
- $line =~ s{(\S+\/podman(-remote)?)((\s+--(root|runroot|runtime|tmpdir|storage-opt|conmon|cgroup-manager|cni-config-dir|storage-driver|events-backend|url) \S+)*)(.*)}{
+ $line =~ s{(\S+\/podman(-remote)?)((\s+--(root|runroot|runtime|tmpdir|storage-opt|conmon|cgroup-manager|network-config-dir|storage-driver|events-backend|url) \S+)*)(.*)}{
my ($full_path, $remote, $options, $args) = ($1, $2||'', $3, $6);
$options =~ s/^\s+//;
diff --git a/contrib/cirrus/logformatter.t b/contrib/cirrus/logformatter.t
index d905693ad..a377faa34 100755
--- a/contrib/cirrus/logformatter.t
+++ b/contrib/cirrus/logformatter.t
@@ -122,17 +122,17 @@ $SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}
[+0103s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_restart_test.go:18
[+0103s] [It] podman pod restart single empty pod
[+0103s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_restart_test.go:41
-[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --cni-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod create --infra=false --share
+[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod create --infra=false --share
[+0103s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
[+0103s] output: 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
-[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --cni-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod restart 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
+[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod restart 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
[+0103s] Error: no containers in pod 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 have no dependencies, cannot start pod: no such container
[+0103s] output:
[+0103s] [AfterEach] Podman pod restart
[+0103s] /var/tmp/go/src/github.com/containers/podman/test/e2e/pod_restart_test.go:28
-[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --cni-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod rm -fa
+[+0103s] Running: /var/tmp/go/src/github.com/containers/podman/bin/podman --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs pod rm -fa
[+0103s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89
-[+0104s] Running: /var/tmp/go/src/github.com/containers/libpod/bin/podman-remote --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --cni-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs --remote --url unix:/run/user/12345/podman-xyz.sock pod rm -fa
+[+0104s] Running: /var/tmp/go/src/github.com/containers/libpod/bin/podman-remote --storage-opt vfs.imagestore=/tmp/podman/imagecachedir --root /tmp/podman_test553496330/crio --runroot /tmp/podman_test553496330/crio-run --runtime /usr/bin/runc --conmon /usr/bin/conmon --network-config-dir /etc/cni/net.d --cgroup-manager systemd --tmpdir /tmp/podman_test553496330 --events-backend file --storage-driver vfs --remote --url unix:/run/user/12345/podman-xyz.sock pod rm -fa
[+0104s] 4810be0cfbd42241e349dbe7d50fbc54405cd320a6637c65fd5323f34d64af89 again
@@ -183,7 +183,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
--conmon /usr/bin/conmon
---cni-config-dir /etc/cni/net.d
+--network-config-dir /etc/cni/net.d
--cgroup-manager systemd
--tmpdir /tmp/podman_test553496330
--events-backend file
@@ -194,7 +194,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
--conmon /usr/bin/conmon
---cni-config-dir /etc/cni/net.d
+--network-config-dir /etc/cni/net.d
--cgroup-manager systemd
--tmpdir /tmp/podman_test553496330
--events-backend file
@@ -208,7 +208,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
--conmon /usr/bin/conmon
---cni-config-dir /etc/cni/net.d
+--network-config-dir /etc/cni/net.d
--cgroup-manager systemd
--tmpdir /tmp/podman_test553496330
--events-backend file
@@ -220,7 +220,7 @@ $SCRIPT_BASE/integration_test.sh |&amp; ${TIMESTAMP}
--runroot /tmp/podman_test553496330/crio-run
--runtime /usr/bin/runc
--conmon /usr/bin/conmon
---cni-config-dir /etc/cni/net.d
+--network-config-dir /etc/cni/net.d
--cgroup-manager systemd
--tmpdir /tmp/podman_test553496330
--events-backend file
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index c52fd9216..6376bafa2 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -12,7 +12,7 @@ set -eo pipefail
# most notably:
#
# PODBIN_NAME : "podman" (i.e. local) or "remote"
-# TEST_ENVIRON : 'host' or 'container'; desired environment in which to run
+# TEST_ENVIRON : 'host', 'host-netavark', or 'container'; desired environment in which to run
# CONTAINER : 1 if *currently* running inside a container, 0 if host
#
@@ -233,8 +233,7 @@ function _run_altbuild() {
make build-no-cgo
;;
*RPM*)
- make -f ./.copr/Makefile
- rpmbuild --rebuild ./podman-*.src.rpm
+ make package
;;
Alt*Cross)
arches=(\
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 8f535c7e7..829bb651d 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -130,7 +130,7 @@ esac
# Required to be defined by caller: The environment where primary testing happens
# shellcheck disable=SC2154
case "$TEST_ENVIRON" in
- host)
+ host*)
# The e2e tests wrongly guess `--cgroup-manager` option
# shellcheck disable=SC2154
if [[ "$CG_FS_TYPE" == "cgroup2fs" ]] || [[ "$PRIV_NAME" == "root" ]]
@@ -141,6 +141,43 @@ case "$TEST_ENVIRON" in
warn "Forcing CGROUP_MANAGER=cgroupfs"
echo "CGROUP_MANAGER=cgroupfs" >> /etc/ci_environment
fi
+ # TODO: For the foreseeable future, need to support running tests
+ # with and without the latest netavark/aardvark. Once they're more
+ # stable and widely supported in Fedora, they can be pre-installed
+ # from its RPM at VM image build-time.
+ if [[ "$TEST_ENVIRON" =~ netavark ]]; then
+ for info in "netavark $NETAVARK_BRANCH $NETAVARK_URL $NETAVARK_DEBUG" \
+ "aardvark-dns $AARDVARK_BRANCH $AARDVARK_URL $AARDVARK_DEBUG"; do
+
+ read _name _branch _url _debug <<<"$info"
+ req_env_vars _name _branch _url _debug
+ msg "Downloading latest $_name from upstream branch '$_branch'"
+ # Use identifiable archive filename in of a get_ci_env.sh environment
+ curl --fail --location -o /tmp/$_name.zip "$_url"
+
+ # Needs to be in a specific location
+ # ref: https://github.com/containers/common/blob/main/pkg/config/config_linux.go#L39
+ _pdir=/usr/local/libexec/podman
+ mkdir -p $_pdir
+ cd $_pdir
+ msg "$PWD"
+ unzip /tmp/$_name.zip
+ if ((_debug)); then
+ warn "Using debug $_name binary"
+ mv $_name.debug $_name
+ else
+ rm $_name.debug
+ fi
+ chmod 0755 $_pdir/$_name
+ cd -
+ done
+
+ restorecon -F -v $_nvdir
+ # This is critical, it signals to all tests that netavark
+ # use is expected.
+ msg "Forcing NETWORK_BACKEND=netavark in all subsequent environments."
+ echo "NETWORK_BACKEND=netavark" >> /etc/ci_environment
+ fi
;;
container)
if ((CONTAINER==0)); then # not yet inside a container
@@ -177,19 +214,26 @@ esac
# Required to be defined by caller: Are we testing as root or a regular user
case "$PRIV_NAME" in
- root) ;;
+ root)
+ if [[ "$TEST_FLAVOR" = "sys" ]]; then
+ # Used in local image-scp testing
+ setup_rootless
+ echo "PODMAN_ROOTLESS_USER=$ROOTLESS_USER" >> /etc/ci_environment
+ fi
+ ;;
rootless)
# load kernel modules since the rootless user has no permission to do so
modprobe ip6_tables || :
modprobe ip6table_nat || :
- # Needs to exist for setup_rootless()
- ROOTLESS_USER="${ROOTLESS_USER:-some${RANDOM}dude}"
- echo "ROOTLESS_USER=$ROOTLESS_USER" >> /etc/ci_environment
setup_rootless
;;
*) die_unknown PRIV_NAME
esac
+if [[ -n "$ROOTLESS_USER" ]]; then
+ echo "ROOTLESS_USER=$ROOTLESS_USER" >> /etc/ci_environment
+fi
+
# Required to be defined by caller: Are we testing podman or podman-remote client
# shellcheck disable=SC2154
case "$PODBIN_NAME" in
@@ -211,7 +255,7 @@ case "$TEST_FLAVOR" in
# Defined in .cirrus.yml
# shellcheck disable=SC2154
if [[ "$ALT_NAME" =~ RPM ]]; then
- bigto dnf install -y glibc-minimal-langpack rpm-build
+ bigto dnf install -y glibc-minimal-langpack go-rpm-macros rpkg rpm-build shadow-utils-subid-devel
fi
;&
docker-py)
@@ -240,19 +284,19 @@ case "$TEST_FLAVOR" in
# Use existing host bits when testing is to happen inside a container
# since this script will run again in that environment.
# shellcheck disable=SC2154
- if [[ "$TEST_ENVIRON" == "host" ]]; then
+ if [[ "$TEST_ENVIRON" =~ host ]]; then
if ((CONTAINER)); then
die "Refusing to config. host-test in container";
fi
remove_packaged_podman_files
- make install PREFIX=/usr ETCDIR=/etc
+ make && make install PREFIX=/usr ETCDIR=/etc
elif [[ "$TEST_ENVIRON" == "container" ]]; then
if ((CONTAINER)); then
remove_packaged_podman_files
- make install PREFIX=/usr ETCDIR=/etc
+ make && make install PREFIX=/usr ETCDIR=/etc
fi
else
- die "Invalid value for $$TEST_ENVIRON=$TEST_ENVIRON"
+ die "Invalid value for \$TEST_ENVIRON=$TEST_ENVIRON"
fi
install_test_configs
@@ -266,7 +310,7 @@ case "$TEST_FLAVOR" in
# Ref: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27270#note_499585550
remove_packaged_podman_files
- make install PREFIX=/usr ETCDIR=/etc
+ make && make install PREFIX=/usr ETCDIR=/etc
msg "Installing docker and containerd"
# N/B: Tests check/expect `docker info` output, and this `!= podman info`
diff --git a/contrib/helloimage/Containerfile b/contrib/helloimage/Containerfile
new file mode 100644
index 000000000..bea71cae0
--- /dev/null
+++ b/contrib/helloimage/Containerfile
@@ -0,0 +1,8 @@
+FROM registry.access.redhat.com/ubi8-micro:latest
+
+LABEL maintainer="Podman Maintainers"
+LABEL artist="Máirín Ní Ḋuḃṫaiġ, Twitter:@mairin"
+WORKDIR /tmp
+
+COPY podman_hello_world.bash .
+ENTRYPOINT ./podman_hello_world.bash
diff --git a/contrib/helloimage/README.md b/contrib/helloimage/README.md
new file mode 100644
index 000000000..93edcc527
--- /dev/null
+++ b/contrib/helloimage/README.md
@@ -0,0 +1,55 @@
+![PODMAN logo](../../logo/podman-logo-source.svg)
+
+# Podman Hello World image
+
+## Overview
+
+This directory contains the Containerfile and bash script necessary to create the
+"hello" podman image housed on quay.io under the Podman account in a public
+repository. The image is public and can be pulled without credentials.
+
+Using this image is helpful to:
+
+ * Prove that basic Podman operations are working on the host.
+ * Shows that the image was pulled from the quay.io container registry.
+ * Container creation was successfuly accomplished. (`podman ps -a`)
+ * The created container was able to stream output to your terminal.
+
+## Directory Contents
+
+The contents of this directory contain:
+ * ./Containerfile
+ * ./podman_hello_world.bash
+
+## Sample Usage
+
+To simply run the image:
+
+```
+podman run quay.io/podman/hello
+
+! ... Hello Podman World ...!
+
+ .--"--.
+ / - - \
+ / (O) (O) \
+ ~~~| -=(,Y,)=- |
+ .---. /` \ |~~
+ ~/ o o \~~~~.----. ~~
+ | =(X)= |~ / (O (O) \
+ ~~~~~~~ ~| =(Y_)=- |
+ ~~~~ ~~~| U |~~
+
+Project: https://github.com/containers/podman
+Website: https://podman.io
+Documents: https://docs.podman.io
+Twitter: @Podman_io
+```
+To build the image yourself, copy the files from this directory into
+a local directory and issue these commands:
+
+```
+chmod 755 ./podman_hello_world.bash
+podman build -t myhello .
+podman run myhello
+```
diff --git a/contrib/helloimage/podman_hello_world.bash b/contrib/helloimage/podman_hello_world.bash
new file mode 100755
index 000000000..c28141174
--- /dev/null
+++ b/contrib/helloimage/podman_hello_world.bash
@@ -0,0 +1,23 @@
+#!/bin/sh
+###
+# ASCII art by the incomparable Máirín Duffy,
+# duffy@redhat.com, Twitter: @mairin
+# January 2022
+###
+echo " "
+echo "! ... Hello Podman World ...!"
+echo " "
+echo " .--\"--. "
+echo " / - - \\ "
+echo " / (O) (O) \\ "
+echo " ~~~| -=(,Y,)=- | "
+echo " .---. /\` \\ |~~ "
+echo " ~/ o o \\~~~~.----. ~~ "
+echo " | =(X)= |~ / (O (O) \\ "
+echo " ~~~~~~~ ~| =(Y_)=- | "
+echo " ~~~~ ~~~| U |~~ "
+echo ""
+echo "Project: https://github.com/containers/podman"
+echo "Website: https://podman.io"
+echo "Documents: https://docs.podman.io"
+echo "Twitter: @Podman_io"
diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs
index c2826fc19..c4ba623c0 100644
--- a/contrib/msi/podman.wxs
+++ b/contrib/msi/podman.wxs
@@ -29,6 +29,9 @@
<Component Id="WinPathExecutable" Guid="00F5B731-D4A6-4B69-87B0-EA4EBAB89F95" Win64="Yes">
<File Id="8F507E28-A61D-4E64-A92B-B5A00F023AE8" Name="winpath.exe" Source="bin/windows/winpath.exe" KeyPath="yes"/>
</Component>
+ <Component Id="WinSshProxyExecutable" Guid="0DA730AB-2F97-40E8-A8FC-356E88EAA4D2" Win64="Yes">
+ <File Id="4A2AD125-34E7-4BD8-BE28-B2A9A5EDBEB5" Name="win-sshproxy.exe" Source="bin/windows/win-sshproxy.exe" KeyPath="yes"/>
+ </Component>
</Directory>
</Directory>
</Directory>
@@ -41,6 +44,7 @@
<ComponentRef Id="INSTALLDIR_Component"/>
<ComponentRef Id="MainExecutable"/>
<ComponentRef Id="WinPathExecutable"/>
+ <ComponentRef Id="WinSshProxyExecutable"/>
<ComponentGroupRef Id="ManFiles"/>
</Feature>
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
deleted file mode 100644
index cb041df6c..000000000
--- a/contrib/spec/podman.spec.in
+++ /dev/null
@@ -1,571 +0,0 @@
-%global with_devel 0
-%global with_bundled 1
-%global with_check 0
-%global with_unit_test 0
-%bcond_without doc
-
-%global debug_package %{nil}
-
-# podman hack directory
-%define hackdir %{_builddir}/%{repo}-%{shortcommit0}
-
-%global provider github
-%global provider_tld com
-%global project containers
-%global repo podman
-# https://github.com/containers/podman
-%global provider_prefix %{provider}.%{provider_tld}/%{project}/%{repo}
-%global import_path %{provider_prefix}
-%global git0 https://%{provider}.%{provider_tld}/%{project}/%{repo}
-%global commit0 #COMMIT#
-%global shortcommit0 %(c=%{commit0}; echo ${c:0:8})
-
-Name: podman
-%if 0%{?fedora}
-Epoch: 99
-%else
-Epoch: 0
-%endif
-Version: 3.3.0
-Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
-Summary: Manage Pods, Containers and Container Images
-License: ASL 2.0
-URL: %{git_podman}
-Source0: %{git0}/archive/%{commit0}/%{repo}-%{shortcommit0}.tar.gz
-Source1: conmon.tar.gz
-# e.g. el6 has ppc64 arch without gcc-go, so EA tag is required
-#ExclusiveArch: %%{?go_arches:%%{go_arches}}%%{!?go_arches:%%{ix86} x86_64 aarch64 %%{arm}}
-ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64
-# The COPR process will uncomment this
-#BuildRequires: golang-bin
-#
-# btrfs-progs-devel package is not available in CentOS/RHEL-8
-%if 0%{?rhel} != 8 && 0%{?centos} != 8
-BuildRequires: btrfs-progs-devel
-%endif
-BuildRequires: glib2-devel
-BuildRequires: glibc-devel
-BuildRequires: glibc-static
-BuildRequires: git
-%if %{with doc}
-BuildRequires: go-md2man
-%endif
-BuildRequires: gpgme-devel
-BuildRequires: libassuan-devel
-BuildRequires: libgpg-error-devel
-BuildRequires: libseccomp-devel
-BuildRequires: libselinux-devel
-BuildRequires: pkgconfig
-BuildRequires: make
-BuildRequires: systemd-devel
-Requires: catatonit >= 0.1.7
-Requires: containers-common
-Requires: conmon
-Requires: containernetworking-plugins >= 0.6.0-3
-Requires: iptables
-%if 0%{?rhel} < 8 || 0%{?centos} < 8
-Requires: container-selinux
-Requires: runc
-%else
-%if 0%{?rhel} || 0%{?centos}
-Requires: runc
-%else
-Requires: oci-runtime
-Recommends: crun
-%endif
-Recommends: container-selinux
-Recommends: slirp4netns
-Recommends: fuse-overlayfs
-Recommends: xz
-%endif
-
-# vendored libraries
-# awk '{print "Provides: bundled(golang("$1")) = "$2}' vendor.conf | sort
-# [thanks to Carl George <carl@george.computer> for containerd.spec]
-Provides: bundled(golang(github.com/Azure/go-ansiterm)) = 19f72df4d05d31cbe1c56bfc8045c96babff6c7e
-Provides: bundled(golang(github.com/blang/semver)) = v3.5.0
-Provides: bundled(golang(github.com/boltdb/bolt)) = master
-Provides: bundled(golang(github.com/buger/goterm)) = 2f8dfbc7dbbff5dd1d391ed91482c24df243b2d3
-Provides: bundled(golang(github.com/BurntSushi/toml)) = v0.2.0
-Provides: bundled(golang(github.com/containerd/cgroups)) = 77e628511d924b13a77cebdc73b757a47f6d751b
-Provides: bundled(golang(github.com/containerd/continuity)) = master
-Provides: bundled(golang(github.com/containernetworking/cni)) = v0.7.0-alpha1
-Provides: bundled(golang(github.com/containernetworking/plugins)) = 1fb94a4222eafc6f948eacdca9c9f2158b427e53
-Provides: bundled(golang(github.com/containers/image)) = c6e0eee0f8eb38e78ae2e44a9aeea0576f451617
-Provides: bundled(golang(github.com/containers/psgo)) = dd34e7e448e5d4f3c7ce87b5da7738b00778dbfd
-Provides: bundled(golang(github.com/containers/storage)) = 8b1a0f8d6863cf05709af333b8997a437652ec4c
-Provides: bundled(golang(github.com/coreos/go-systemd)) = v14
-Provides: bundled(golang(github.com/cri-o/ocicni)) = master
-Provides: bundled(golang(github.com/cyphar/filepath-securejoin)) = v0.2.1
-Provides: bundled(golang(github.com/davecgh/go-spew)) = v1.1.0
-Provides: bundled(golang(github.com/docker/distribution)) = 7a8efe719e55bbfaff7bc5718cdf0ed51ca821df
-Provides: bundled(golang(github.com/docker/docker)) = 86f080cff0914e9694068ed78d503701667c4c00
-Provides: bundled(golang(github.com/docker/docker-credential-helpers)) = d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
-Provides: bundled(golang(github.com/docker/go-connections)) = 3ede32e2033de7505e6500d6c868c2b9ed9f169d
-Provides: bundled(golang(github.com/docker/go-units)) = v0.3.2
-Provides: bundled(golang(github.com/docker/libtrust)) = aabc10ec26b754e797f9028f4589c5b7bd90dc20
-Provides: bundled(golang(github.com/docker/spdystream)) = ed496381df8283605c435b86d4fdd6f4f20b8c6e
-Provides: bundled(golang(github.com/fatih/camelcase)) = f6a740d52f961c60348ebb109adde9f4635d7540
-Provides: bundled(golang(github.com/fsnotify/fsnotify)) = 7d7316ed6e1ed2de075aab8dfc76de5d158d66e1
-Provides: bundled(golang(github.com/fsouza/go-dockerclient)) = master
-Provides: bundled(golang(github.com/ghodss/yaml)) = 04f313413ffd65ce25f2541bfd2b2ceec5c0908c
-Provides: bundled(golang(github.com/godbus/dbus)) = a389bdde4dd695d414e47b755e95e72b7826432c
-Provides: bundled(golang(github.com/gogo/protobuf)) = c0656edd0d9eab7c66d1eb0c568f9039345796f7
-Provides: bundled(golang(github.com/golang/glog)) = 23def4e6c14b4da8ac2ed8007337bc5eb5007998
-Provides: bundled(golang(github.com/golang/groupcache)) = b710c8433bd175204919eb38776e944233235d03
-Provides: bundled(golang(github.com/golang/protobuf)) = 4bd1920723d7b7c925de087aa32e2187708897f7
-Provides: bundled(golang(github.com/googleapis/gnostic)) = 0c5108395e2debce0d731cf0287ddf7242066aba
-Provides: bundled(golang(github.com/google/gofuzz)) = 44d81051d367757e1c7c6a5a86423ece9afcf63c
-Provides: bundled(golang(github.com/gorilla/context)) = v1.1
-Provides: bundled(golang(github.com/gorilla/mux)) = v1.3.0
-Provides: bundled(golang(github.com/hashicorp/errwrap)) = 7554cd9344cec97297fa6649b055a8c98c2a1e55
-Provides: bundled(golang(github.com/hashicorp/golang-lru)) = 0a025b7e63adc15a622f29b0b2c4c3848243bbf6
-Provides: bundled(golang(github.com/hashicorp/go-multierror)) = 83588e72410abfbe4df460eeb6f30841ae47d4c4
-Provides: bundled(golang(github.com/imdario/mergo)) = 0.2.2
-Provides: bundled(golang(github.com/json-iterator/go)) = 1.0.0
-Provides: bundled(golang(github.com/kr/pty)) = v1.0.0
-Provides: bundled(golang(github.com/mattn/go-runewidth)) = v0.0.1
-Provides: bundled(golang(github.com/Microsoft/go-winio)) = 78439966b38d69bf38227fbf57ac8a6fee70f69a
-Provides: bundled(golang(github.com/Microsoft/hcsshim)) = 43f9725307998e09f2e3816c2c0c36dc98f0c982
-Provides: bundled(golang(github.com/mistifyio/go-zfs)) = v2.1.1
-Provides: bundled(golang(github.com/mrunalp/fileutils)) = master
-Provides: bundled(golang(github.com/mtrmac/gpgme)) = b2432428689ca58c2b8e8dea9449d3295cf96fc9
-Provides: bundled(golang(github.com/Nvveen/Gotty)) = master
-Provides: bundled(golang(github.com/opencontainers/go-digest)) = v1.0.0-rc0
-Provides: bundled(golang(github.com/opencontainers/image-spec)) = v1.0.0
-Provides: bundled(golang(github.com/opencontainers/runc)) = 6e15bc3f92fd4c58b3285e8f27eaeb6b22d62920
-Provides: bundled(golang(github.com/opencontainers/runtime-spec)) = v1.0.0
-Provides: bundled(golang(github.com/opencontainers/runtime-tools)) = 625e2322645b151a7cbb93a8b42920933e72167f
-Provides: bundled(golang(github.com/opencontainers/selinux)) = b6fa367ed7f534f9ba25391cc2d467085dbb445a
-Provides: bundled(golang(github.com/openshift/imagebuilder)) = master
-Provides: bundled(golang(github.com/pkg/errors)) = v0.8.0
-Provides: bundled(golang(github.com/pmezard/go-difflib)) = 792786c7400a136282c1664665ae0a8db921c6c2
-Provides: bundled(golang(github.com/pquerna/ffjson)) = d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac
-Provides: bundled(golang(github.com/containers/buildah)) = a2c8358455f9b6a254c572455af2a0afcfcec544
-Provides: bundled(golang(github.com/seccomp/containers-golang)) = master
-Provides: bundled(golang(github.com/seccomp/libseccomp-golang)) = v0.9.0
-Provides: bundled(golang(github.com/sirupsen/logrus)) = v1.0.0
-Provides: bundled(golang(github.com/spf13/pflag)) = 9ff6c6923cfffbcd502984b8e0c80539a94968b7
-Provides: bundled(golang(github.com/stretchr/testify)) = 4d4bfba8f1d1027c4fdbe371823030df51419987
-Provides: bundled(golang(github.com/syndtr/gocapability)) = e7cb7fa329f456b3855136a2642b197bad7366ba
-Provides: bundled(golang(github.com/tchap/go-patricia)) = v2.2.6
-Provides: bundled(golang(github.com/ulikunitz/xz)) = v0.5.4
-# "-" are not accepted in version strings, so comment out below line
-#Provides: bundled(golang(github.com/urfave/cli)) = fix-short-opts-parsing
-Provides: bundled(golang(github.com/vbatts/tar-split)) = v0.10.2
-Provides: bundled(golang(github.com/vishvananda/netlink)) = master
-Provides: bundled(golang(github.com/vishvananda/netns)) = master
-Provides: bundled(golang(github.com/xeipuuv/gojsonpointer)) = master
-Provides: bundled(golang(github.com/xeipuuv/gojsonreference)) = master
-Provides: bundled(golang(github.com/xeipuuv/gojsonschema)) = master
-Provides: bundled(golang(golang.org/x/crypto)) = 81e90905daefcd6fd217b62423c0908922eadb30
-Provides: bundled(golang(golang.org/x/net)) = c427ad74c6d7a814201695e9ffde0c5d400a7674
-Provides: bundled(golang(golang.org/x/sys)) = master
-Provides: bundled(golang(golang.org/x/text)) = f72d8390a633d5dfb0cc84043294db9f6c935756
-Provides: bundled(golang(golang.org/x/time)) = f51c12702a4d776e4c1fa9b0fabab841babae631
-Provides: bundled(golang(google.golang.org/grpc)) = v1.0.4
-Provides: bundled(golang(gopkg.in/cheggaaa/pb.v1)) = v1.0.7
-Provides: bundled(golang(gopkg.in/inf.v0)) = v0.9.0
-Provides: bundled(golang(gopkg.in/mgo.v2)) = v2
-Provides: bundled(golang(gopkg.in/square/go-jose.v2)) = v2.1.3
-Provides: bundled(golang(gopkg.in/yaml.v2)) = v2
-Provides: bundled(golang(k8s.io/api)) = 5ce4aa0bf2f097f6021127b3d879eeda82026be8
-Provides: bundled(golang(k8s.io/apiextensions-apiserver)) = 1b31e26d82f1ec2e945c560790e98f34bb5f2e63
-Provides: bundled(golang(k8s.io/apimachinery)) = 616b23029fa3dc3e0ccefd47963f5651a6543d94
-Provides: bundled(golang(k8s.io/apiserver)) = 4d1163080139f1f9094baf8a3a6099e85e1867f6
-Provides: bundled(golang(k8s.io/client-go)) = 7cd1d3291b7d9b1e2d54d4b69eb65995eaf8888e
-Provides: bundled(golang(k8s.io/kube-openapi)) = 275e2ce91dec4c05a4094a7b1daee5560b555ac9
-Provides: bundled(golang(k8s.io/utils)) = 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e
-
-%description
-%{summary}
-%{repo} provides a library for applications looking to use
-the Container Pod concept popularized by Kubernetes.
-
-%package remote
-Summary: Remote Podman client
-
-%description -n podman-remote
-%{summary}
-This package provides the Podman remote client which
-can be used to access Podman running on a server.
-
-%if 0%{?with_devel}
-%package devel
-Summary: Library for applications looking to use Container Pods
-BuildArch: noarch
-Provides: %{repo}-devel = %{version}-%{release}
-
-%if 0%{?with_check} && ! 0%{?with_bundled}
-BuildRequires: golang(github.com/BurntSushi/toml)
-BuildRequires: golang(github.com/containerd/cgroups)
-BuildRequires: golang(github.com/containernetworking/plugins/pkg/ns)
-BuildRequires: golang(github.com/containers/image/copy)
-BuildRequires: golang(github.com/containers/image/directory)
-BuildRequires: golang(github.com/containers/image/docker)
-BuildRequires: golang(github.com/containers/image/docker/archive)
-BuildRequires: golang(github.com/containers/image/docker/reference)
-BuildRequires: golang(github.com/containers/image/docker/tarfile)
-BuildRequires: golang(github.com/containers/image/image)
-BuildRequires: golang(github.com/containers/image/oci/archive)
-BuildRequires: golang(github.com/containers/image/pkg/strslice)
-BuildRequires: golang(github.com/containers/image/pkg/sysregistriesv2)
-BuildRequires: golang(github.com/containers/image/signature)
-BuildRequires: golang(github.com/containers/image/storage)
-BuildRequires: golang(github.com/containers/image/tarball)
-BuildRequires: golang(github.com/containers/image/transports/alltransports)
-BuildRequires: golang(github.com/containers/image/types)
-BuildRequires: golang(github.com/containers/storage)
-BuildRequires: golang(github.com/containers/storage/pkg/archive)
-BuildRequires: golang(github.com/containers/storage/pkg/idtools)
-BuildRequires: golang(github.com/containers/storage/pkg/reexec)
-BuildRequires: golang(github.com/coreos/go-systemd/dbus)
-BuildRequires: golang(github.com/cri-o/ocicni/pkg/ocicni)
-BuildRequires: golang(github.com/docker/distribution/reference)
-BuildRequires: golang(github.com/docker/docker/daemon/caps)
-BuildRequires: golang(github.com/docker/docker/pkg/mount)
-BuildRequires: golang(github.com/docker/docker/pkg/namesgenerator)
-BuildRequires: golang(github.com/docker/docker/pkg/stringid)
-BuildRequires: golang(github.com/docker/docker/pkg/system)
-BuildRequires: golang(github.com/docker/docker/pkg/term)
-BuildRequires: golang(github.com/docker/docker/pkg/truncindex)
-BuildRequires: golang(github.com/ghodss/yaml)
-BuildRequires: golang(github.com/godbus/dbus)
-BuildRequires: golang(github.com/mattn/go-sqlite3)
-BuildRequires: golang(github.com/mrunalp/fileutils)
-BuildRequires: golang(github.com/opencontainers/go-digest)
-BuildRequires: golang(github.com/opencontainers/image-spec/specs-go/v1)
-BuildRequires: golang(github.com/opencontainers/runc/libcontainer)
-BuildRequires: golang(github.com/opencontainers/runtime-spec/specs-go)
-BuildRequires: golang(github.com/opencontainers/runtime-tools/generate)
-BuildRequires: golang(github.com/opencontainers/selinux/go-selinux)
-BuildRequires: golang(github.com/opencontainers/selinux/go-selinux/label)
-BuildRequires: golang(github.com/pkg/errors)
-BuildRequires: golang(github.com/sirupsen/logrus)
-BuildRequires: golang(golang.org/x/crypto/ssh/terminal)
-BuildRequires: golang(golang.org/x/sys/unix)
-BuildRequires: golang(k8s.io/apimachinery/pkg/util/wait)
-BuildRequires: golang(k8s.io/client-go/tools/remotecommand)
-BuildRequires: golang(k8s.io/kubernetes/pkg/kubelet/container)
-%endif
-
-Requires: golang(github.com/BurntSushi/toml)
-Requires: golang(github.com/containerd/cgroups)
-Requires: golang(github.com/containernetworking/plugins/pkg/ns)
-Requires: golang(github.com/containers/image/copy)
-Requires: golang(github.com/containers/image/directory)
-Requires: golang(github.com/containers/image/docker)
-Requires: golang(github.com/containers/image/docker/archive)
-Requires: golang(github.com/containers/image/docker/reference)
-Requires: golang(github.com/containers/image/docker/tarfile)
-Requires: golang(github.com/containers/image/image)
-Requires: golang(github.com/containers/image/oci/archive)
-Requires: golang(github.com/containers/image/pkg/strslice)
-Requires: golang(github.com/containers/image/pkg/sysregistriesv2)
-Requires: golang(github.com/containers/image/signature)
-Requires: golang(github.com/containers/image/storage)
-Requires: golang(github.com/containers/image/tarball)
-Requires: golang(github.com/containers/image/transports/alltransports)
-Requires: golang(github.com/containers/image/types)
-Requires: golang(github.com/containers/storage)
-Requires: golang(github.com/containers/storage/pkg/archive)
-Requires: golang(github.com/containers/storage/pkg/idtools)
-Requires: golang(github.com/containers/storage/pkg/reexec)
-Requires: golang(github.com/coreos/go-systemd/dbus)
-Requires: golang(github.com/cri-o/ocicni/pkg/ocicni)
-Requires: golang(github.com/docker/distribution/reference)
-Requires: golang(github.com/docker/docker/daemon/caps)
-Requires: golang(github.com/docker/docker/pkg/mount)
-Requires: golang(github.com/docker/docker/pkg/namesgenerator)
-Requires: golang(github.com/docker/docker/pkg/stringid)
-Requires: golang(github.com/docker/docker/pkg/system)
-Requires: golang(github.com/docker/docker/pkg/term)
-Requires: golang(github.com/docker/docker/pkg/truncindex)
-Requires: golang(github.com/ghodss/yaml)
-Requires: golang(github.com/godbus/dbus)
-Requires: golang(github.com/mattn/go-sqlite3)
-Requires: golang(github.com/mrunalp/fileutils)
-Requires: golang(github.com/opencontainers/go-digest)
-Requires: golang(github.com/opencontainers/image-spec/specs-go/v1)
-Requires: golang(github.com/opencontainers/runc/libcontainer)
-Requires: golang(github.com/opencontainers/runtime-spec/specs-go)
-Requires: golang(github.com/opencontainers/runtime-tools/generate)
-Requires: golang(github.com/opencontainers/selinux/go-selinux)
-Requires: golang(github.com/opencontainers/selinux/go-selinux/label)
-Requires: golang(github.com/pkg/errors)
-Requires: golang(github.com/sirupsen/logrus)
-Requires: golang(golang.org/x/crypto/ssh/terminal)
-Requires: golang(golang.org/x/sys/unix)
-Requires: golang(k8s.io/apimachinery/pkg/util/wait)
-Requires: golang(k8s.io/client-go/tools/remotecommand)
-Requires: golang(k8s.io/kubernetes/pkg/kubelet/container)
-
-Provides: golang(%{import_path}/cmd/%{name}/docker) = %{version}-%{release}
-Provides: golang(%{import_path}/cmd/%{name}/formats) = %{version}-%{release}
-Provides: golang(%{import_path}/libkpod) = %{version}-%{release}
-Provides: golang(%{import_path}/libpod) = %{version}-%{release}
-Provides: golang(%{import_path}/libpod/common) = %{version}-%{release}
-Provides: golang(%{import_path}/libpod/driver) = %{version}-%{release}
-Provides: golang(%{import_path}/libpod/layers) = %{version}-%{release}
-Provides: golang(%{import_path}/pkg/annotations) = %{version}-%{release}
-Provides: golang(%{import_path}/pkg/chrootuser) = %{version}-%{release}
-Provides: golang(%{import_path}/pkg/registrar) = %{version}-%{release}
-Provides: golang(%{import_path}/pkg/storage) = %{version}-%{release}
-Provides: golang(%{import_path}/utils) = %{version}-%{release}
-
-%description -n libpod-devel
-%{summary}
-
-This package contains library source intended for
-building other packages which use import path with
-%{import_path} prefix.
-%endif
-
-%if 0%{?with_unit_test} && 0%{?with_devel}
-%package unit-test-devel
-Summary: Unit tests for %{name} package
-%if 0%{?with_check}
-#Here comes all BuildRequires: PACKAGE the unit tests
-#in %%check section need for running
-%endif
-
-# test subpackage tests code from devel subpackage
-Requires: %{name}-devel = %{version}-%{release}
-
-%if 0%{?with_check} && ! 0%{?with_bundled}
-BuildRequires: golang(github.com/stretchr/testify/assert)
-BuildRequires: golang(github.com/urfave/cli)
-%endif
-
-Requires: golang(github.com/stretchr/testify/assert)
-Requires: golang(github.com/urfave/cli)
-
-%description unit-test-devel
-%{summary}
-libpod provides a library for applications looking to use the Container Pod concept popularized by Kubernetes.
-
-This package contains unit tests for project
-providing packages with %{import_path} prefix.
-%endif
-
-%if %{with doc}
-%package manpages
-Summary: Man pages for the %{name} commands
-BuildArch: noarch
-
-%description manpages
-Man pages for the %{name} commands
-%endif
-
-%if 0%{?fedora} && ! 0%{?centos}
-%package tests
-Summary: Tests for %{name}
-
-Requires: %{name} = %{epoch}:%{version}-%{release}
-Requires: gnupg
-Requires: bats
-Requires: jq
-Requires: skopeo
-Requires: nmap-ncat
-Requires: httpd-tools
-Requires: openssl
-Requires: socat
-Requires: buildah
-
-%description tests
-%{summary}
-
-This package contains system tests for %{name}
-%endif
-
-%prep
-%autosetup -Sgit -n %{repo}-%{shortcommit0}
-
-# untar conmon
-tar zxf %{SOURCE1}
-
-%build
-mkdir _build
-pushd _build
-
-# These flags should work for all rpm distros and arches
-export CGO_CFLAGS="-O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -ffat-lto-objects -fexceptions -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
-
-%if 0%{?fedora} || 0%{?rhel}
-# This flag is only present on RH-family distros
-export CGO_CFLAGS+=" -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1"
-%endif
-
-%ifnarch %{ix86}
-# Build fails on i686 with this flag
-export CGO_CFLAGS+=" -D_FILE_OFFSET_BITS=64"
-%endif
-
-%ifarch x86_64
-# Builds only on x86_64 with this flag
-export CGO_CFLAGS+=" -m64 -mtune=generic"
-%if 0%{?fedora} || 0%{?rhel} >= 8
-# Build fails on rhel7 and non-86_64 with this flag
-export CGO_CFLAGS+=" -fcf-protection"
-%endif
-%endif
-
-mkdir -p src/%{provider}.%{provider_tld}/%{project}
-ln -s ../../../../ src/%{import_path}
-popd
-ln -s vendor src
-export GO111MODULE=on
-export GOPATH=$(pwd)/_build:$(pwd):$(pwd):%{gopath}
-export BUILDTAGS="selinux seccomp systemd $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh) $(%{hackdir}/hack/libdm_tag.sh) exclude_graphdriver_devicemapper"
-
-%if %{with doc}
-BUILDTAGS=$BUILDTAGS make binaries docs
-%else
-BUILDTAGS=$BUILDTAGS make binaries
-%endif
-
-%install
-install -dp %{buildroot}%{_unitdir}
-install -dp %{buildroot}%{_usr}/lib/systemd/user
-PODMAN_VERSION=%{version} %{__make} DESTDIR=%{buildroot} PREFIX=%{_prefix} ETCDIR=%{_sysconfdir} \
- install.bin-nobuild \
- install.remote-nobuild \
-%if %{with doc}
- install.man-nobuild \
-%endif
- install.systemd \
- install.completions
-
-mv pkg/hooks/README.md pkg/hooks/README-hooks.md
-
-# source codes for building projects
-%if 0%{?with_devel}
-install -d -p %{buildroot}/%{gopath}/src/%{import_path}/
-
-echo "%%dir %%{gopath}/src/%%{import_path}/." >> devel.file-list
-# find all *.go but no *_test.go files and generate devel.file-list
-for file in $(find . \( -iname "*.go" -or -iname "*.s" \) \! -iname "*_test.go" | grep -v "vendor") ; do
- dirprefix=$(dirname $file)
- install -d -p %{buildroot}/%{gopath}/src/%{import_path}/$dirprefix
- cp -pav $file %{buildroot}/%{gopath}/src/%{import_path}/$file
- echo "%%{gopath}/src/%%{import_path}/$file" >> devel.file-list
-
- while [ "$dirprefix" != "." ]; do
- echo "%%dir %%{gopath}/src/%%{import_path}/$dirprefix" >> devel.file-list
- dirprefix=$(dirname $dirprefix)
- done
-done
-%endif
-
-%if 0%{?fedora} && ! 0%{?centos}
-install -d -p %{buildroot}/%{_datadir}/%{name}/test/system
-cp -pav test/system %{buildroot}/%{_datadir}/%{name}/test/
-%endif
-
-# testing files for this project
-%if 0%{?with_unit_test} && 0%{?with_devel}
-install -d -p %{buildroot}/%{gopath}/src/%{import_path}/
-# find all *_test.go files and generate unit-test-devel.file-list
-for file in $(find . -iname "*_test.go" | grep -v "vendor") ; do
- dirprefix=$(dirname $file)
- install -d -p %{buildroot}/%{gopath}/src/%{import_path}/$dirprefix
- cp -pav $file %{buildroot}/%{gopath}/src/%{import_path}/$file
- echo "%%{gopath}/src/%%{import_path}/$file" >> unit-test-devel.file-list
-
- while [ "$dirprefix" != "." ]; do
- echo "%%dir %%{gopath}/src/%%{import_path}/$dirprefix" >> devel.file-list
- dirprefix=$(dirname $dirprefix)
- done
-done
-%endif
-
-%if 0%{?with_devel}
-sort -u -o devel.file-list devel.file-list
-%endif
-
-%check
-%if 0%{?with_check} && 0%{?with_unit_test} && 0%{?with_devel}
-%if ! 0%{?with_bundled}
-export GOPATH=%{buildroot}/%{gopath}:%{gopath}
-%else
-# Since we aren't packaging up the vendor directory we need to link
-# back to it somehow. Hack it up so that we can add the vendor
-# directory from BUILD dir as a gopath to be searched when executing
-# tests from the BUILDROOT dir.
-ln -s ./ ./vendor/src # ./vendor/src -> ./vendor
-
-export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath}
-%endif
-
-%if ! 0%{?gotest:1}
-%global gotest go test
-%endif
-
-%gotest %{import_path}/cmd/%{name}
-%gotest %{import_path}/libkpod
-%gotest %{import_path}/libpod
-%gotest %{import_path}/pkg/registrar
-%endif
-
-#define license tag if not already defined
-%{!?_licensedir:%global license %doc}
-
-%files
-%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
-%{_bindir}/%{name}
-%{_datadir}/bash-completion/completions/*
-%{_datadir}/zsh/site-functions/*
-%{_datadir}/fish/vendor_completions.d/*
-%{_unitdir}/podman-auto-update.service
-%{_unitdir}/podman-auto-update.timer
-%{_unitdir}/podman.service
-%{_unitdir}/podman.socket
-%{_unitdir}/podman-restart.service
-%{_usr}/lib/systemd/user/podman.service
-%{_usr}/lib/systemd/user/podman.socket
-%{_usr}/lib/systemd/user/podman-auto-update.service
-%{_usr}/lib/systemd/user/podman-auto-update.timer
-%{_usr}/lib/systemd/user/podman-restart.service
-%{_usr}/lib/tmpfiles.d/podman.conf
-%dir %{_libexecdir}/%{name}
-%{_libexecdir}/%{name}/rootlessport
-
-%if 0%{?with_devel}
-%files -n libpod-devel -f devel.file-list
-%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
-%dir %{gopath}/src/%{provider}.%{provider_tld}/%{project}
-%endif
-
-%if 0%{?with_unit_test} && 0%{?with_devel}
-%files unit-test-devel -f unit-test-devel.file-list
-%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
-%endif
-
-%files -n podman-remote
-%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
-%{_bindir}/%{name}-remote
-
-%if %{with doc}
-%files manpages
-%{_mandir}/man1/*.1*
-%{_mandir}/man5/*.5*
-%endif
-
-%if 0%{?fedora} && ! 0%{?centos}
-%files tests
-%license LICENSE
-%{_datadir}/%{name}/test
-%dir %{_datadir}/%{name}/test/system
-%endif
-
-%changelog
-* Sat Aug 4 2018 Dan Walsh <dwalsh@redhat.com> - 0.8.1-1.git6b4ab2a
-- Bump to v0.8.1
-
-* Sun Jul 29 2018 Lokesh Mandvekar (Bot) <lsm5+bot@fedoraproject.org> - 0.8.10.8.1-1.dev.git1a439f9.dev.git5a4e590.dev.git433cbd51
-- bump to 0.8.1
-- autobuilt 433cbd5
diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md
index b86b981d2..985cfa0e8 100644
--- a/docs/source/markdown/podman-attach.1.md
+++ b/docs/source/markdown/podman-attach.1.md
@@ -10,7 +10,7 @@ podman\-attach - Attach to a running container
## DESCRIPTION
**podman attach** attaches to a running *container* using the *container's name* or *ID*, to either view its ongoing output or to control it interactively.\
-The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** OPTION, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
+The *container* can be detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** OPTION, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
## OPTIONS
#### **--detach-keys**=**sequence**
@@ -22,7 +22,7 @@ The default is `ctrl-p,ctrl-q`.
Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\
The default is **false**.\
-*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.*
+*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.*
#### **--no-stdin**
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 474597938..2c8f4005c 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -29,7 +29,7 @@ still be used by other tools when manually preprocessing them via `cpp -E`.
When the URL is an archive, the contents of the URL is downloaded to a temporary
location and extracted before execution.
-When the URL is an Containerfile, the Containerfile is downloaded to a temporary
+When the URL is a Containerfile, the Containerfile is downloaded to a temporary
location.
When a Git repository is set as the URL, the repository is cloned locally and
@@ -94,7 +94,7 @@ resulting image's configuration.
#### **--cache-from**
Images to utilize as potential cache sources. Podman does not currently support
-caching so this is a NOOP. (This option is not available with the remote Podman client)
+caching so this is a NOOP. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--cap-add**=*CAP\_xxx*
@@ -119,7 +119,7 @@ given.
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--cgroup-parent**=*path*
@@ -138,7 +138,7 @@ that the cgroup namespace in which `buildah` itself is being run should be reuse
This option is added to be aligned with other containers CLIs.
Podman doesn't communicate with a daemon or a remote server.
-Thus, compressing the data before sending it is irrelevant to Podman. (This option is not available with the remote Podman client)
+Thus, compressing the data before sending it is irrelevant to Podman. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--cpu-period**=*limit*
@@ -173,7 +173,7 @@ proportion can be modified by changing the container's CPU share weighting
relative to the weighting of all other running containers.
To modify the proportion from the default of 1024, use the **--cpu-shares**
-flag to set the weighting to 2 or higher.
+option to set the weighting to 2 or higher.
The proportion will only apply when CPU-intensive processes are running.
When tasks in one container are idle, other containers can use the
@@ -256,8 +256,8 @@ specifying **--disable-compression=false**.
#### **--disable-content-trust**
This is a Docker specific option to disable image verification to a container
-registry and is not supported by Podman. This flag is a NOOP and provided
-solely for scripting compatibility. (This option is not available with the remote Podman client)
+registry and is not supported by Podman. This option is a NOOP and provided
+solely for scripting compatibility. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--dns**=*dns*
@@ -266,7 +266,7 @@ Set custom DNS servers to be used during the build.
This option can be used to override the DNS configuration passed to the
container. Typically this is necessary when the host DNS configuration is
invalid for the container (e.g., 127.0.0.1). When this is the case the `--dns`
-flag is necessary for every run.
+option is necessary for every run.
The special value **none** can be specified to disable creation of
/etc/resolv.conf in the container by Podman. The /etc/resolv.conf file in the
@@ -343,7 +343,7 @@ another process.
Controls what type of isolation is used for running processes as part of `RUN`
instructions. Recognized types include *oci* (OCI-compatible runtime, the
default), *rootless* (OCI-compatible runtime invoked using a modified
-configuration and its --rootless flag enabled, with *--no-new-keyring
+configuration and its --rootless option enabled, with *--no-new-keyring
--no-pivot* added to its *create* invocation, with network and UTS namespaces
disabled, and IPC, PID, and user namespaces enabled; the default for
unprivileged users), and *chroot* (an internal wrapper that leans more toward
@@ -364,7 +364,7 @@ Add an image *label* (e.g. label=*value*) to the image metadata. Can be used
multiple times.
Users can set a special LABEL **io.containers.capabilities=CAP1,CAP2,CAP3** in
-a Containerfile that specified the list of Linux capabilities required for the
+a Containerfile that specifies the list of Linux capabilities required for the
container to run properly. This label specified in a container image tells
Podman to run the container with just these capabilities. Podman launches the
container with just the specified capabilities, as long as this list of
@@ -405,7 +405,7 @@ trillions).
#### **--memory-swap**=*LIMIT*
A limit value equal to memory plus swap. Must be used with the **-m**
-(**--memory**) flag. The swap `LIMIT` should always be larger than **-m**
+(**--memory**) option. The swap `LIMIT` should always be larger than **-m**
(**--memory**) value. By default, the swap `LIMIT` will be set to double
the value of --memory.
@@ -424,7 +424,8 @@ Valid _mode_ values are:
container full access to local system services such as D-bus and is therefore
considered insecure.
- **ns:**_path_: path to a network namespace to join.
-- **private**: create a new namespace for the container (default).
+- **private**: create a new namespace for the container (default)
+- **\<network name|ID\>**: Join the network with the given name or ID, e.g. use `--network mynet` to join the network with the name mynet. Only supported for rootful users.
#### **--no-cache**
@@ -454,7 +455,7 @@ architecture of the host (for example `linux/arm`). If `--platform` is set,
then the values of the `--arch`, `--os`, and `--variant` options will be
overridden.
-The `--platform` flag can be specified more than once, or given a
+The `--platform` option can be specified more than once, or given a
comma-separated list of values as its argument. When more than one platform is
specified, the `--manifest` option should be used instead of the `--tag`
option.
@@ -471,23 +472,21 @@ the help of emulation provided by packages like `qemu-user-static`.
#### **--pull**
-When the option is specified or set to "true", pull the image. Raise an error
-if the image could not be pulled, even if the image is present locally.
+When the option is enabled or set explicitly to `true` (with *--pull=true*)
+pull the image from the first registry it is found in as listed in registries.conf.
+Raise an error if the image could not be pulled, even if the image is present locally.
-If the option is disabled (with *--pull=false*) or not specified, pull the
-image from the registry only if the image is not present locally. Raise an
-error if the image is not found in the registries and is not present locally.
+If the option is disabled (with *--pull=false*), pull the image from the
+registry only if the image is not present locally. Raise an error if the image is not
+in the registries and not present locally.
-#### **--pull-always**
+If the pull option is set to `always` (with *--pull=always*),
+pull the image from the first registry it is found in as listed in registries.conf.
+Raise an error if not found in the registries, even if the image is present locally.
-Pull the image from the first registry it is found in as listed in
-registries.conf. Raise an error if not found in the registries, even if the
-image is present locally.
-
-#### **--pull-never**
-
-Do not pull the image from the registry, use only the local version. Raise an
-error if the image is not present locally.
+If the pull option is set to `never` (with *--pull=never*),
+Do not pull the image from the registry, use only the local version. Raise an error
+if the image is not present locally.
#### **--quiet**, **-q**
@@ -513,7 +512,7 @@ Pass secret information to be used in the Containerfile for building images
in a safe way that will not end up stored in the final image, or be seen in other stages.
The secret will be mounted in the container at the default location of `/run/secrets/id`.
-To later use the secret, use the --mount flag in a `RUN` instruction within a `Containerfile`:
+To later use the secret, use the --mount option in a `RUN` instruction within a `Containerfile`:
`RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret`
@@ -547,7 +546,7 @@ size entirely, the system uses `64m`.
#### **--sign-by**=*fingerprint*
-Sign the image using a GPG key with the specified FINGERPRINT. (This option is not available with the remote Podman client)
+Sign the image using a GPG key with the specified FINGERPRINT. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines,)
#### **--squash**
@@ -564,7 +563,7 @@ image) into a single new layer.
SSH agent socket or keys to expose to the build.
The socket path can be left empty to use the value of `default=$SSH_AUTH_SOCK`
-To later use the ssh agent, use the --mount flag in a `RUN` instruction within a `Containerfile`:
+To later use the ssh agent, use the --mount option in a `RUN` instruction within a `Containerfile`:
`RUN --mount=type=ssh,id=id mycmd`
@@ -601,7 +600,7 @@ timestamp.
#### **--tls-verify**
Require HTTPS and verify certificates when talking to container registries
-(defaults to true). (This option is not available with the remote Podman client)
+(defaults to true). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--ulimit**=*type*=*soft-limit*[:*hard-limit*]
@@ -711,7 +710,7 @@ than being relative to the host as it would be when run rootfull.
#### **--uts**=*how*
-Sets the configuration for UTS namespaces when the handling `RUN` instructions.
+Sets the configuration for UTS namespaces when handling `RUN` instructions.
The configured value can be "" (the empty string) or "container" to indicate
that a new UTS namespace should be created, or it can be "host" to indicate
that the UTS namespace in which `podman` itself is being run should be reused,
@@ -728,7 +727,7 @@ using the architecture variant of the build host.
Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman
bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman
- container. (This option is not available with the remote Podman client)
+ container. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup>
@@ -889,6 +888,8 @@ $ podman build --no-cache -t imageName .
$ podman build --layers --force-rm -t imageName .
$ podman build --no-cache --rm=false -t imageName .
+
+$ podman build --network mynet .
```
### Building a multi-architecture image using the --manifest option (requires emulation software)
@@ -954,7 +955,7 @@ $ podman build -f dev/Containerfile https://10.10.10.1/podman/context.tar.gz
### .containerignore/.dockerignore
If the file *.containerignore* or *.dockerignore* exists in the context directory,
-`podman build` reads its contents. Use the `--ignorefile` flag to override the
+`podman build` reads its contents. Use the `--ignorefile` option to override the
.containerignore path location.
Podman uses the content to exclude files and directories from the context
directory, when executing COPY and ADD directives in the
diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md
index 00d8f7095..fcb3cfd0c 100644
--- a/docs/source/markdown/podman-container-checkpoint.1.md
+++ b/docs/source/markdown/podman-container-checkpoint.1.md
@@ -57,7 +57,7 @@ The default is **false**.
Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\
The default is **false**.\
-*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.*
+*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.*
#### **--leave-running**, **-R**
diff --git a/docs/source/markdown/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md
index e58519ac3..0f182eded 100644
--- a/docs/source/markdown/podman-container-cleanup.1.md
+++ b/docs/source/markdown/podman-container-cleanup.1.md
@@ -27,7 +27,7 @@ Can only be specified if a single *container* is being cleaned up (conflicts wit
Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\
The default is **false**.\
-*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.*
+*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.*
#### **--rm**
diff --git a/docs/source/markdown/podman-container-diff.1.md b/docs/source/markdown/podman-container-diff.1.md
index 89a749fbd..f09bc4896 100644
--- a/docs/source/markdown/podman-container-diff.1.md
+++ b/docs/source/markdown/podman-container-diff.1.md
@@ -26,7 +26,7 @@ Alter the output into a different format. The only valid format for **podman con
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md
index d059276d7..cc5defe6b 100644
--- a/docs/source/markdown/podman-container-exists.1.md
+++ b/docs/source/markdown/podman-container-exists.1.md
@@ -23,21 +23,21 @@ The default is **false**.
## EXAMPLES
-Check if an container called "webclient" exists in local storage. Here, the container does exist.
+Check if a container called "webclient" exists in local storage. Here, the container does exist.
```
$ podman container exists webclient
$ echo $?
0
```
-Check if an container called "webbackend" exists in local storage. Here, the container does not exist.
+Check if a container called "webbackend" exists in local storage. Here, the container does not exist.
```
$ podman container exists webbackend
$ echo $?
1
```
-Check if an container called "ubi8-working-container" created via Buildah exists in local storage. Here, the container does not exist.
+Check if a container called "ubi8-working-container" created via Buildah exists in local storage. Here, the container does not exist.
```
$ podman container exists --external ubi8-working-container
$ echo $?
diff --git a/docs/source/markdown/podman-container-inspect.1.md b/docs/source/markdown/podman-container-inspect.1.md
index dfed294fc..9945fca7c 100644
--- a/docs/source/markdown/podman-container-inspect.1.md
+++ b/docs/source/markdown/podman-container-inspect.1.md
@@ -23,7 +23,7 @@ The keys of the returned JSON can be used as the values for the --format flag (s
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
to run containers such as CRI-O, the last started container could be from either of those methods.
-(This option is not available with the remote Podman client.)
+(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines.)
#### **--size**, **-s**
diff --git a/docs/source/markdown/podman-container-prune.1.md b/docs/source/markdown/podman-container-prune.1.md
index 494500ca1..b20936c15 100644
--- a/docs/source/markdown/podman-container-prune.1.md
+++ b/docs/source/markdown/podman-container-prune.1.md
@@ -20,12 +20,12 @@ Supported filters:
| Filter | Description |
| :----------------: | --------------------------------------------------------------------------- |
-| *until* | Only remove containers and images created before given timestamp. |
-| *label* | Only remove containers and images, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *label* | Only remove containers, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *until* | Only remove containers created before given timestamp. |
-The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes containers with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes containers without the specified labels.
-The `label` *filter* accepts two formats. One is the `label`=*key*, `label`=*key*=*value*, which removes containers with the specified labels. The other format is the `label!`=*key*, or `label!`=*key*=*value*, which removes containers without the specified labels.
+The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
#### **--force**, **-f**
diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md
index 3dfa063b8..4016eb1cb 100644
--- a/docs/source/markdown/podman-container-restore.1.md
+++ b/docs/source/markdown/podman-container-restore.1.md
@@ -33,7 +33,7 @@ The default is **false**.
Instead of providing the *container ID* or *name*, use the last created *container*. If other tools than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either tool.\
The default is **false**.\
-*IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.*
+*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.*
#### **--ignore-rootfs**
@@ -87,7 +87,7 @@ not much the container runtime used for container creation.
Import a pre-checkpoint tar.gz file which was exported by Podman. This option
must be used with **-i** or **--import**. It only works on `runc 1.0-rc3` or `higher`.
-*IMPORTANT: This OPTION is not supported on the remote client.*
+*IMPORTANT: This OPTION is not supported on the remote client, including Mac and Windows (excluding WSL2) machines.*
#### **--name**, **-n**=*name*
diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md
index 2457265dd..ac34b232c 100644
--- a/docs/source/markdown/podman-container-runlabel.1.md
+++ b/docs/source/markdown/podman-container-runlabel.1.md
@@ -42,7 +42,7 @@ Display the label's value of the image having populated its environment variable
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--creds**=*[username[:password]]*
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 62028de40..2a0f3b738 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -25,7 +25,7 @@ man pages.
## IMAGE
The image is specified using transport:path format. If no transport is specified, the `docker` (container registry)
-transport will be used by default. For remote Podman, `docker` is the only allowed transport.
+transport will be used by default. For remote Podman, including Mac and Windows (excluding WSL2) machines, `docker` is the only allowed transport.
**dir:**_path_
An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This
@@ -127,7 +127,7 @@ If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the d
#### **--cgroups**=*mode*
Determines whether the container will create CGroups.
-Valid values are *enabled*, *disabled*, *no-conmon*, *split*, which the default being *enabled*.
+Valid values are *enabled*, *disabled*, *no-conmon*, *split*, with the default being *enabled*.
The *enabled* option will create a new cgroup under the cgroup-parent.
The *disabled* option will force the container to not create CGroups, and thus conflicts with CGroup options (**--cgroupns** and **--cgroup-parent**).
@@ -149,7 +149,7 @@ Write the container ID to the file
#### **--conmon-pidfile**=*path*
Write the pid of the `conmon` process to a file. `conmon` runs in a separate process than Podman, so this is necessary when using systemd to restart Podman containers.
-(This option is not available with the remote Podman client)
+(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--cpu-period**=*limit*
@@ -308,7 +308,7 @@ Set custom DNS servers. Invalid if using **--dns** and **--network** that is set
This option can be used to override the DNS
configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., 127.0.0.1). When this
-is the case the **--dns** flags is necessary for every run.
+is the case the **--dns** flag is necessary for every run.
The special value **none** can be specified to disable creation of **/etc/resolv.conf** in the container by Podman.
The **/etc/resolv.conf** file in the image will be used without changes.
@@ -348,7 +348,7 @@ See [**Environment**](#environment) note below for precedence and examples.
#### **--env-host**
-Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client)
+Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--env-file**=*file*
@@ -369,7 +369,7 @@ Note: the **--gidmap** flag cannot be called in conjunction with the **--pod** f
#### **--group-add**=*group|keep-groups*
-Add additional groups to assign to primary user running within the container process.
+Assign additional groups to the primary user running within the container process.
- `keep-groups` is a special flag that tells Podman to keep the supplementary group access.
@@ -377,7 +377,7 @@ Allows container to use the user's supplementary group access. If file systems o
devices are only accessible by the rootless user's group, this flag tells the OCI
runtime to pass the group access into the container. Currently only available
with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups
-with this flag. (Not available for remote commands)
+with this flag. (Not available for remote commands, including Mac and Windows (excluding WSL2) machines)
#### **--health-cmd**=*"command"* | *'["command", "arg1", ...]'*
@@ -432,7 +432,7 @@ the container should not use any proxy. Proxy environment variables specified
for the container in any other way will override the values that would have
been passed through from the host. (Other ways to specify the proxy for the
container include passing the values with the `--env` flag, or hard coding the
-proxy environment at container build time.) (This option is not available with the remote Podman client)
+proxy environment at container build time.) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
For example, to disable passing these environment variables from host to
container:
@@ -524,7 +524,7 @@ $ podman info --format '{{ .Host.LogDriver }}'
journald
```
The *passthrough* driver passes down the standard streams (stdin, stdout, stderr) to the
-container. It is not allowed with the remote Podman client and on a tty, since it is
+container. It is not allowed with the remote Podman client, including Mac and Windows (excluding WSL2) machines, and on a tty, since it is
vulnerable to attacks via TIOCSTI.
#### **--log-opt**=*name*=*value*
@@ -695,7 +695,7 @@ Valid _mode_ values are:
- **alias=name**: Add network-scoped alias for the container.
- **ip=IPv4**: Specify a static ipv4 address for this container.
- **ip=IPv6**: Specify a static ipv6 address for this container.
- - **mac=MAC**: Specify a static mac address address for this container.
+ - **mac=MAC**: Specify a static mac address for this container.
- **interface_name**: Specify a name for the created network interface inside the container.
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
@@ -715,7 +715,7 @@ Valid _mode_ values are:
- **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only).
- **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to.
- **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
- Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
+ Note: Rootlesskit changes the source IP address of incoming packets to an IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
- **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks.
#### **--network-alias**=*alias*
@@ -739,6 +739,8 @@ This option conflicts with **--add-host**.
Whether to disable OOM Killer for the container or not.
+This flag is not supported on cgroups V2 systems.
+
#### **--oom-score-adj**=*num*
Tune the host's OOM preferences for containers (accepts -1000 to 1000)
@@ -1028,7 +1030,7 @@ Podman will setup tmpfs mount points in the following directories:
It will also set the default stop signal to SIGRTMIN+3.
-This allow systemd to run in a confined container without any modifications.
+This allows systemd to run in a confined container without any modifications.
Note: On `SELinux` systems, systemd attempts to write to the cgroup
file system. Containers writing to the cgroup file system are denied by default.
@@ -1197,7 +1199,7 @@ The `--userns=auto` flag, requires that the user name `containers` and a range o
Example: `containers:2147483647:2147483648`.
-Podman allocates unique ranges of UIDs and GIDs from the `containers` subpordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
+Podman allocates unique ranges of UIDs and GIDs from the `containers` subordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
Valid `auto` options:
@@ -1235,7 +1237,7 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman
bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman
container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume
in the host to the container. If no such named volume exists, Podman will
-create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.)
+create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.)
The _options_ is a comma-separated list and can be:
@@ -1307,7 +1309,7 @@ Only the current container can use a private volume.
Note: Do not relabel system files and directories. Relabeling system content
might cause other confined services on your machine to fail. For these types
-of containers we recommend that disable SELinux separation. The option
+of containers we recommend disabling SELinux separation. The option
`--security-opt label=disable` disables SELinux separation for containers used in the build.
For example if a user wanted to volume mount their entire home directory into a
container, they need to disable SELinux separation.
@@ -1372,7 +1374,7 @@ the volume will not be able to change their privilege. By default volumes
are mounted with `nosuid`.
Mounting the volume with the noexec option means that no executables on the
-volume will be able to executed within the container.
+volume will be able to be executed within the container.
Mounting the volume with the nodev option means that no devices on the volume
will be able to be used by processes within the container. By default volumes
@@ -1443,7 +1445,7 @@ can override the working directory by using the **-w** option.
#### **--pidfile**=*path*
-When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client)
+When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile.
After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command:
@@ -1540,7 +1542,7 @@ $ podman create --network net1:ip=10.89.1.5 --network net2:ip=10.89.10.10 alpine
### Rootless Containers
-Podman runs as a non root user on most systems. This feature requires that a new enough version of shadow-utils
+Podman runs as a non-root user on most systems. This feature requires that a new enough version of shadow-utils
be installed. The shadow-utils package must include the newuidmap and newgidmap executables.
Note: RHEL7 and Centos 7 will not have this feature until RHEL7.7 is released.
diff --git a/docs/source/markdown/podman-diff.1.md b/docs/source/markdown/podman-diff.1.md
index fd574abb1..66675de93 100644
--- a/docs/source/markdown/podman-diff.1.md
+++ b/docs/source/markdown/podman-diff.1.md
@@ -26,7 +26,7 @@ Alter the output into a different format. The only valid format for **podman di
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md
index c539e987b..5fb4ceace 100644
--- a/docs/source/markdown/podman-exec.1.md
+++ b/docs/source/markdown/podman-exec.1.md
@@ -37,7 +37,7 @@ When set to true, keep stdin open even if not attached. The default is *false*.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--preserve-fds**=*N*
diff --git a/docs/source/markdown/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md
index 3586341a9..8cd35140e 100644
--- a/docs/source/markdown/podman-generate-kube.1.md
+++ b/docs/source/markdown/podman-generate-kube.1.md
@@ -6,7 +6,7 @@ podman-generate-kube - Generate Kubernetes YAML based on containers, pods or vol
**podman generate kube** [*options*] *container...* | *pod...* | *volume...*
## DESCRIPTION
-**podman generate kube** will generate Kubernetes YAML (v1 specification) from Podman containers, pods or volumes. Whether
+**podman generate kube** will generate Kubernetes YAML (v1 specification) from Podman containers, pods or volumes. Regardless of whether
the input is for containers or pods, Podman will always generate the specification as a Pod. The input may be in the form
of one or more containers, pods or volumes names or IDs.
diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md
index 363d042ae..fdc9c21a5 100644
--- a/docs/source/markdown/podman-generate-systemd.1.md
+++ b/docs/source/markdown/podman-generate-systemd.1.md
@@ -10,7 +10,7 @@ podman\-generate\-systemd - Generate systemd unit file(s) for a container or pod
**podman generate systemd** will create a systemd unit file that can be used to control a container or pod.
By default, the command will print the content of the unit files to stdout.
-_Note: If you use this command with the remote client, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._
+_Note: If you use this command with the remote client, including Mac and Windows (excluding WSL2) machines, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._
## OPTIONS
@@ -68,6 +68,22 @@ Set the systemd unit name prefix for pods. The default is *pod*.
Set the systemd unit name separator between the name/id of a container/pod and the prefix. The default is *-*.
+#### **--wants**=*dependency_name*
+
+Add the systemd unit wants (`Wants=`) option, that this service is (weak) dependent on. This option may be specified more than once. This option does not influence the order in which services are started or stopped.
+
+User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden.
+
+#### **--after**=*dependency_name*
+
+Add the systemd unit after (`After=`) option, that ordering dependencies between the list of dependencies and this service. This option may be specified more than once.
+
+User-defined dependencies will be appended to the generated unit file, but any existing options such as needed or defined by default (e.g. `online.target`) will **not** be removed or overridden.
+
+#### **--requires**=*dependency_name*
+
+Set the systemd unit requires (`Requires=`) option. Similar to wants, but declares a stronger requirement dependency.
+
#### **--template**
Add template specifiers to run multiple services from the systemd unit file.
diff --git a/docs/source/markdown/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md
index 153e3bfe8..db17f97fb 100644
--- a/docs/source/markdown/podman-image-prune.1.md
+++ b/docs/source/markdown/podman-image-prune.1.md
@@ -25,16 +25,19 @@ Remove images even when they are used by external containers (e.g., build contai
Provide filter values.
-The --filter flag format is of “key=value”. If there is more than one filter, then pass multiple flags (e.g., --filter "foo=bar" --filter "bif=baz")
+The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*.
Supported filters:
-- `until` (_timestamp_) - only remove containers and images created before given timestamp
-- `label` (label=_key_, label=_key=value_, label!=_key_, or label!=_key=value_) - only remove containers and images, with (or without, in case label!=... is used) the specified labels.
+| Filter | Description |
+| :----------------: | --------------------------------------------------------------------------- |
+| *label* | Only remove images, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *until* | Only remove images created before given timestamp. |
-The until filter can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
-The label filter accepts two formats. One is the label=... (label=_key_ or label=_key=value_), which removes images with the specified labels. The other format is the label!=... (label!=_key_ or label!=_key=value_), which removes images without the specified labels.
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes containers with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes containers without the specified labels.
+
+The `until` *filter* can be Unix timestamps, date formatted timestamps or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
#### **--force**, **-f**
diff --git a/docs/source/markdown/podman-image-scp.1.md b/docs/source/markdown/podman-image-scp.1.md
index d39882417..e08d5b465 100644
--- a/docs/source/markdown/podman-image-scp.1.md
+++ b/docs/source/markdown/podman-image-scp.1.md
@@ -8,7 +8,7 @@ podman-image-scp - Securely copy an image from one host to another
## DESCRIPTION
**podman image scp** copies container images between hosts on a network. You can load to the remote host or from the remote host as well as in between two remote hosts.
-Note: `::` is used to specify the image name depending on if you are saving or loading. Images can also be transferred from rootful to rootless storage on the same machine without using sshd. This feature is not supported on the remote client.
+Note: `::` is used to specify the image name depending on if you are saving or loading. Images can also be transferred from rootful to rootless storage on the same machine without using sshd. This feature is not supported on the remote client, including Mac and Windows (excluding WSL2) machines.
**podman image scp [GLOBAL OPTIONS]**
diff --git a/docs/source/markdown/podman-image-sign.1.md b/docs/source/markdown/podman-image-sign.1.md
index 8758b8861..7e483a3b2 100644
--- a/docs/source/markdown/podman-image-sign.1.md
+++ b/docs/source/markdown/podman-image-sign.1.md
@@ -33,7 +33,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--directory**, **-d**=*dir*
@@ -56,7 +56,7 @@ The write (and read) location for signatures is defined in YAML-based
configuration files in /etc/containers/registries.d/ for root,
or $HOME/.config/containers/registries.d for non-root users. When you sign
an image, Podman will use those configuration files to determine
-where to write the signature based on the the name of the originating
+where to write the signature based on the name of the originating
registry or a default storage value unless overridden with the --directory
option. For example, consider the following configuration file.
diff --git a/docs/source/markdown/podman-image-trust.1.md b/docs/source/markdown/podman-image-trust.1.md
index 61b8966a7..ba8d7fc2f 100644
--- a/docs/source/markdown/podman-image-trust.1.md
+++ b/docs/source/markdown/podman-image-trust.1.md
@@ -8,7 +8,7 @@ podman\-image\-trust - Manage container registry image trust policy
**podman image trust** set|show [*options*] *registry[/repository]*
## DESCRIPTION
-Manages which registries you trust as a source of container images based on its location. (This option is not available with the remote Podman client)
+Manages which registries you trust as a source of container images based on its location. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
The location is determined
by the transport and the registry host of the image. Using this container image `docker://docker.io/library/busybox`
diff --git a/docs/source/markdown/podman-images.1.md b/docs/source/markdown/podman-images.1.md
index 8db291fb4..f1d9d4816 100644
--- a/docs/source/markdown/podman-images.1.md
+++ b/docs/source/markdown/podman-images.1.md
@@ -25,27 +25,32 @@ Show image digests
#### **--filter**=*filter*, **-f**
-Filter output based on conditions provided
+Provide filter values.
- Filters:
+The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*.
- **since=IMAGE**
- Filter on images created after the given IMAGE (name or tag).
+Supported filters:
- **before=IMAGE**
- Filter on images created before the given IMAGE (name or tag).
+| Filter | Description |
+| :----------------: | --------------------------------------------------------------------------------------------- |
+| *before* | Filter by images created before the given IMAGE (name or tag). |
+| *dangling* | Filter by dangling (unused) images. |
+| *label* | Filter by images with (or without, in the case of label!=[...] is used) the specified labels. |
+| *readonly* | Filter by read-only or read/write images. |
+| *reference* | Filter by image name. |
+| *since* | Filter by images created after the given IMAGE (name or tag). |
- **dangling
- 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 image. They are denoted with the `<none>` tag, consume disk space and serve no active purpose.
+The `before` *filter* accepts formats: `<image-name>[:<tag>]`, `<image id>` or `<image@digest>`.
- **label**
- Filter by images labels key and/or value.
+The `dangling` *filter* shows images that are taking up disk space and serve no purpose. Dangling image is a file system layer that was used in a previous build of an image and is no longer referenced by any image. They are denoted with the `<none>` tag, consume disk space and serve no active purpose.
- **readonly
- Show only read only images or Read/Write images. The default is to show both. Read/Only images can be configured by modifying the "additionalimagestores" in the /etc/containers/storage.conf file.
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which shows images with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which shows images without the specified labels.
- **reference=**
- Filter by image name, specified as regular expressions.
+The `readonly` *filter* shows, as a default, both read-only and read/write images. Read-only images can be configured by modifying the `additionalimagestores` in the `/etc/containers/storage.conf` file.
+
+The `reference` *filter* accepts the pattern of an image reference `<image-name>[:<tag>]`.
+
+The `since` *filter* accepts formats: `<image-name>[:<tag>]`, `<image id>` or `<image@digest>`.
#### **--format**=*format*
diff --git a/docs/source/markdown/podman-init.1.md b/docs/source/markdown/podman-init.1.md
index 6d1d92e04..d771c92f3 100644
--- a/docs/source/markdown/podman-init.1.md
+++ b/docs/source/markdown/podman-init.1.md
@@ -25,7 +25,7 @@ Initialize all containers. Containers that have already initialized (including c
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md
index 259a6c992..9eafb7460 100644
--- a/docs/source/markdown/podman-inspect.1.md
+++ b/docs/source/markdown/podman-inspect.1.md
@@ -37,7 +37,7 @@ The keys of the returned JSON can be used as the values for the --format flag (s
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
to run containers such as CRI-O, the last started container could be from either of those methods.
-This option can be used to inspect the latest pod created when used with --type pod. (This option is not available with the remote Podman client or when invoked as *podman image inspect*.)
+This option can be used to inspect the latest pod created when used with --type pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines, or when invoked as *podman image inspect*.)
#### **--size**, **-s**
diff --git a/docs/source/markdown/podman-kill.1.md b/docs/source/markdown/podman-kill.1.md
index dc79a44dc..79d93bc4e 100644
--- a/docs/source/markdown/podman-kill.1.md
+++ b/docs/source/markdown/podman-kill.1.md
@@ -23,7 +23,7 @@ Read container ID from the specified file and remove the container. Can be spec
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--signal**, **-s**
diff --git a/docs/source/markdown/podman-load.1.md b/docs/source/markdown/podman-load.1.md
index d1735750f..30e8e82ea 100644
--- a/docs/source/markdown/podman-load.1.md
+++ b/docs/source/markdown/podman-load.1.md
@@ -30,7 +30,7 @@ Note: `:` is a restricted character and cannot be part of the file name.
Load the specified input file instead of from stdin. The file can be on the local file system or on a server (e.g., https://server.com/archive.tar)
-The remote client requires the use of this option.
+The remote client, including Mac and Windows (excluding WSL2) machines, requires the use of this option.
NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of container images. Podman defaults to use `/var/tmp`.
diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md
index ae1eeeafa..c84b0cc99 100644
--- a/docs/source/markdown/podman-login.1.md
+++ b/docs/source/markdown/podman-login.1.md
@@ -38,7 +38,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--get-login**
diff --git a/docs/source/markdown/podman-logs.1.md b/docs/source/markdown/podman-logs.1.md
index 888279990..f62a66c81 100644
--- a/docs/source/markdown/podman-logs.1.md
+++ b/docs/source/markdown/podman-logs.1.md
@@ -20,13 +20,13 @@ any logs at the time you execute podman logs).
Follow log output. Default is false.
Note: If you are following a container which is removed `podman container rm`
-or removed on exit `podman run --rm ...`, then there is a chance the the log
+or removed on exit `podman run --rm ...`, then there is a chance that the log
file will be removed before `podman logs` reads the final content.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--names**, **-n**
diff --git a/docs/source/markdown/podman-machine-list.1.md b/docs/source/markdown/podman-machine-list.1.md
index d68b8b1ca..d1333f1e2 100644
--- a/docs/source/markdown/podman-machine-list.1.md
+++ b/docs/source/markdown/podman-machine-list.1.md
@@ -32,14 +32,14 @@ Valid placeholders for the Go template are listed below:
| .DiskSize | Disk size of machine |
| .LastUp | Time machine was last up |
| .LastUp | Time since the VM was last run |
-| .Memory | Allocated memeory for machine |
+| .Memory | Allocated memory for machine |
| .Name | VM name |
| .Running | Is machine running |
| .Stream | Stream name |
| .VMType | VM type |
| .Port | SSH Port to use to connect to VM|
| .RemoteUsername | VM Username for rootless Podman |
-| .IdentityPath | Path to ssh identify file |
+| .IdentityPath | Path to ssh identity file |
#### **--help**
diff --git a/docs/source/markdown/podman-manifest-add.1.md b/docs/source/markdown/podman-manifest-add.1.md
index 8e3f56797..40f841bf8 100644
--- a/docs/source/markdown/podman-manifest-add.1.md
+++ b/docs/source/markdown/podman-manifest-add.1.md
@@ -44,7 +44,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--creds**=*creds*
diff --git a/docs/source/markdown/podman-manifest-push.1.md b/docs/source/markdown/podman-manifest-push.1.md
index 38201555e..a0011cea8 100644
--- a/docs/source/markdown/podman-manifest-push.1.md
+++ b/docs/source/markdown/podman-manifest-push.1.md
@@ -30,7 +30,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--creds**=*creds*
@@ -78,22 +78,22 @@ Require HTTPS and verify certificates when talking to container registries. (def
**dir:**_path_
An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This is a non-standardized format, primarily useful for debugging or noninvasive container inspection.
- $ podman manfiest push mylist:v1.11 dir:/tmp/mylist
+ $ podman manifest push mylist:v1.11 dir:/tmp/mylist
**docker://**_docker-reference_
An image in a registry implementing the "Docker Registry HTTP API V2". By default, uses the authorization state in `$XDG_RUNTIME_DIR/containers/auth.json`, which is set using `(podman login)`. If the authorization state is not found there, `$HOME/.docker/config.json` is checked, which is set using `(docker login)`.
- $ podman manfiest push mylist:v1.11 docker://registry.example.org/mylist:v1.11
+ $ podman manifest push mylist:v1.11 docker://registry.example.org/mylist:v1.11
**docker-archive:**_path_[**:**_docker-reference_]
An image is stored in the `docker save` formatted file. _docker-reference_ is only used when creating such a file, and it must not contain a digest.
- $ podman manfiest push mylist:v1.11 docker-archive:/tmp/mylist
+ $ podman manifest push mylist:v1.11 docker-archive:/tmp/mylist
**docker-daemon:**_docker-reference_
An image in _docker-reference_ format stored in the docker daemon internal storage. _docker-reference_ must contain a tag.
- $ podman manfiest push mylist:v1.11 docker-daemon:registry.example.org/mylist:v1.11
+ $ podman manifest push mylist:v1.11 docker-daemon:registry.example.org/mylist:v1.11
**oci-archive:**_path_**:**_tag_
An image _tag_ in a directory compliant with "Open Container Image Layout Specification" at _path_.
diff --git a/docs/source/markdown/podman-mount.1.md b/docs/source/markdown/podman-mount.1.md
index a4ce25bce..82c7fe804 100644
--- a/docs/source/markdown/podman-mount.1.md
+++ b/docs/source/markdown/podman-mount.1.md
@@ -14,7 +14,7 @@ accessed from the host, and returns its location.
If you execute the command without any arguments, Podman will list all of the
currently mounted containers, including external containers. External containers are
-containers in container/storage by tools other then Podman. For example Buildah and
+containers in container/storage by tools other than Podman. For example Buildah and
CRI-O.
Rootless mode only supports mounting VFS driver, unless you enter the user namespace
@@ -38,7 +38,7 @@ Print the mounted containers in specified format (json).
Instead of providing the container name or ID, use the last created container.
If you use methods other than Podman to run containers such as CRI-O, the last
-started container could be from either of those methods. (This option is not available with the remote Podman client)
+started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--no-trunc**
diff --git a/docs/source/markdown/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md
index d48509581..5be0c2595 100644
--- a/docs/source/markdown/podman-network-create.1.md
+++ b/docs/source/markdown/podman-network-create.1.md
@@ -39,14 +39,15 @@ Additionally the `bridge` driver supports the following option:
The `macvlan` and `ipvlan` driver support the following options:
- `parent`: The host device which should be used for the macvlan interface. Defaults to the default route interface.
-- `mode`: This options sets the specified ip/macvlan mode on the interface.
+- `mode`: This option sets the specified ip/macvlan mode on the interface.
- Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`.
- Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`.
#### **--gateway**
Define a gateway for the subnet. If you want to provide a gateway address, you must also provide a
-*subnet* option.
+*subnet* option. Can be specified multiple times.
+The argument order of the **--subnet**, **--gateway** and **--ip-range** options must match.
#### **--internal**
@@ -56,7 +57,8 @@ automatically disabled.
#### **--ip-range**
Allocate container IP from a range. The range must be a complete subnet and in CIDR notation. The *ip-range* option
-must be used with a *subnet* option.
+must be used with a *subnet* option. Can be specified multiple times.
+The argument order of the **--subnet**, **--gateway** and **--ip-range** options must match.
#### **--label**
@@ -64,11 +66,13 @@ Set metadata for a network (e.g., --label mykey=value).
#### **--subnet**
-The subnet in CIDR notation.
+The subnet in CIDR notation. Can be specified multiple times to allocate more than one subnet for this network.
+The argument order of the **--subnet**, **--gateway** and **--ip-range** options must match.
+This is useful to set a static ipv4 and ipv6 subnet.
#### **--ipv6**
-Enable IPv6 (Dual Stack) networking.
+Enable IPv6 (Dual Stack) networking. If not subnets are given it will allocate a ipv4 and ipv6 subnet.
## EXAMPLE
@@ -102,6 +106,12 @@ $ podman network create --subnet 192.168.55.0/24 --ip-range 192.168.55.128/25
cni-podman5
```
+Create a network with a static ipv4 and ipv6 subnet and set a gateway.
+```
+$ podman network create --subnet 192.168.55.0/24 --gateway 192.168.55.3 --subnet fd52:2a5a:747e:3acd::/64 --gateway fd52:2a5a:747e:3acd::10
+podman4
+```
+
Create a Macvlan based network using the host interface eth0. Macvlan networks can only be used as root.
```
# podman network create -d macvlan -o parent=eth0 newnet
diff --git a/docs/source/markdown/podman-network-exists.1.md b/docs/source/markdown/podman-network-exists.1.md
index ee62a830e..44c145cd9 100644
--- a/docs/source/markdown/podman-network-exists.1.md
+++ b/docs/source/markdown/podman-network-exists.1.md
@@ -29,7 +29,7 @@ $ echo $?
$
```
-Check if an network called `webbackend` exists (the network does not actually exist).
+Check if a network called `webbackend` exists (the network does not actually exist).
```
$ podman network exists webbackend
$ echo $?
diff --git a/docs/source/markdown/podman-network-prune.1.md b/docs/source/markdown/podman-network-prune.1.md
index d35decb1b..a1dc5d85c 100644
--- a/docs/source/markdown/podman-network-prune.1.md
+++ b/docs/source/markdown/podman-network-prune.1.md
@@ -18,17 +18,20 @@ Do not prompt for confirmation
#### **--filter**
-Filter output based on conditions given.
-Multiple filters can be given with multiple uses of the --filter option.
-Filters with the same key work inclusive with the only exception being
-`label` which is exclusive. Filters with different keys always work exclusive.
+Provide filter values.
-Valid filters are listed below:
+The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*.
-| **Filter** | **Description** |
-| ---------- | ------------------------------------------------------------------------------------- |
-| label | [Key] or [Key=Value] Label assigned to a network |
-| until | only remove networks created before given timestamp |
+Supported filters:
+
+| Filter | Description |
+| :----------------: | --------------------------------------------------------------------------- |
+| *label* | Only remove networks, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *until* | Only remove networks created before given timestamp. |
+
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes networks with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes networks without the specified labels.
+
+The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
## EXAMPLE
Prune networks
diff --git a/docs/source/markdown/podman-network-reload.1.md b/docs/source/markdown/podman-network-reload.1.md
index f091c34dc..5cbe9b9bf 100644
--- a/docs/source/markdown/podman-network-reload.1.md
+++ b/docs/source/markdown/podman-network-reload.1.md
@@ -21,7 +21,7 @@ Reload network configuration of all containers.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md
index 390058b4a..6d02af80d 100644
--- a/docs/source/markdown/podman-play-kube.1.md
+++ b/docs/source/markdown/podman-play-kube.1.md
@@ -40,7 +40,7 @@ A Kubernetes PersistentVolumeClaim represents a Podman named volume. Only the Pe
- volume.podman.io/mount-options
Play kube is capable of building images on the fly given the correct directory layout and Containerfiles. This
-option is not available for remote clients yet. Consider the following excerpt from a YAML file:
+option is not available for remote clients, including Mac and Windows (excluding WSL2) machines, yet. Consider the following excerpt from a YAML file:
```
apiVersion: v1
kind: Pod
@@ -120,7 +120,7 @@ Build images even if they are found in the local storage.
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--configmap**=*path*
@@ -179,7 +179,7 @@ Valid _mode_ values are:
- **alias=name**: Add network-scoped alias for the container.
- **ip=IPv4**: Specify a static ipv4 address for this container.
- **ip=IPv6**: Specify a static ipv6 address for this container.
- - **mac=MAC**: Specify a static mac address address for this container.
+ - **mac=MAC**: Specify a static mac address for this container.
- **interface_name**: Specify a name for the created network interface inside the container.
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
@@ -198,7 +198,7 @@ Valid _mode_ values are:
- **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only).
- **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to.
- **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
- Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
+ Note: Rootlesskit changes the source IP address of incoming packets to an IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
- **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks.
#### **--no-hosts**
@@ -215,7 +215,7 @@ Tears down the pods created by a previous run of `play kube` and recreates the p
#### **--seccomp-profile-root**=*path*
-Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (This option is not available with the remote Podman client)
+Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--start**
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index 1ff0cbec1..8088e1d62 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -171,7 +171,7 @@ Valid _mode_ values are:
- **alias=name**: Add network-scoped alias for the container.
- **ip=IPv4**: Specify a static ipv4 address for this container.
- **ip=IPv6**: Specify a static ipv6 address for this container.
- - **mac=MAC**: Specify a static mac address address for this container.
+ - **mac=MAC**: Specify a static mac address for this container.
- **interface_name**: Specify a name for the created network interface inside the container.
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
@@ -191,7 +191,7 @@ Valid _mode_ values are:
- **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only).
- **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to.
- **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
- Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
+ Note: Rootlesskit changes the source IP address of incoming packets to an IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
- **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks.
#### **--network-alias**=*alias*
@@ -323,7 +323,7 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman
bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman
container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume
in the host to the container. If no such named volume exists, Podman will
-create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.)
+create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.)
The _options_ is a comma-separated list and can be:
diff --git a/docs/source/markdown/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md
index 5147a2559..75b422306 100644
--- a/docs/source/markdown/podman-pod-inspect.1.md
+++ b/docs/source/markdown/podman-pod-inspect.1.md
@@ -14,7 +14,7 @@ that belong to the pod.
#### **--latest**, **-l**
Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman
-to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client)
+to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--format**=*format*, **-f**
diff --git a/docs/source/markdown/podman-pod-kill.1.md b/docs/source/markdown/podman-pod-kill.1.md
index 973d8da88..45b61c620 100644
--- a/docs/source/markdown/podman-pod-kill.1.md
+++ b/docs/source/markdown/podman-pod-kill.1.md
@@ -17,7 +17,7 @@ Sends signal to all containers associated with a pod.
#### **--latest**, **-l**
Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman
-to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client)
+to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--signal**, **-s**
diff --git a/docs/source/markdown/podman-pod-logs.1.md b/docs/source/markdown/podman-pod-logs.1.md
index 5adcd9df5..53aa5d58b 100644
--- a/docs/source/markdown/podman-pod-logs.1.md
+++ b/docs/source/markdown/podman-pod-logs.1.md
@@ -22,11 +22,11 @@ By default `podman pod logs` retrieves logs for all the containers available wit
Follow log output. Default is false.
Note: If you are following a pod which is removed `podman pod rm`, then there is a
-chance the the log file will be removed before `podman pod logs` reads the final content.
+chance that the log file will be removed before `podman pod logs` reads the final content.
#### **--latest**, **-l**
-Instead of providing the pod name or id, get logs of the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or id, get logs of the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--since**=*TIMESTAMP*
diff --git a/docs/source/markdown/podman-pod-pause.1.md b/docs/source/markdown/podman-pod-pause.1.md
index 0e53b52be..1f29cb2ed 100644
--- a/docs/source/markdown/podman-pod-pause.1.md
+++ b/docs/source/markdown/podman-pod-pause.1.md
@@ -17,7 +17,7 @@ Pause all pods.
#### **--latest**, **-l**
-Instead of providing the pod name or ID, pause the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, pause the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md
index b61f12e90..a0581df50 100644
--- a/docs/source/markdown/podman-pod-ps.1.md
+++ b/docs/source/markdown/podman-pod-ps.1.md
@@ -42,7 +42,7 @@ Display the container statuses
#### **--latest**, **-l**
-Show the latest pod created (all states) (This option is not available with the remote Podman client)
+Show the latest pod created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--noheading**
diff --git a/docs/source/markdown/podman-pod-restart.1.md b/docs/source/markdown/podman-pod-restart.1.md
index c63daa419..677eca3a3 100644
--- a/docs/source/markdown/podman-pod-restart.1.md
+++ b/docs/source/markdown/podman-pod-restart.1.md
@@ -20,7 +20,7 @@ Restarts all pods
#### **--latest**, **-l**
-Instead of providing the pod name or ID, restart the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, restart the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-pod-rm.1.md b/docs/source/markdown/podman-pod-rm.1.md
index 00c82a8f7..ed33c5e57 100644
--- a/docs/source/markdown/podman-pod-rm.1.md
+++ b/docs/source/markdown/podman-pod-rm.1.md
@@ -23,7 +23,7 @@ ExecStop directive of a systemd service referencing that pod.
#### **--latest**, **-l**
-Instead of providing the pod name or ID, remove the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, remove the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--force**, **-f**
diff --git a/docs/source/markdown/podman-pod-start.1.md b/docs/source/markdown/podman-pod-start.1.md
index 7f3adc8ff..bab109212 100644
--- a/docs/source/markdown/podman-pod-start.1.md
+++ b/docs/source/markdown/podman-pod-start.1.md
@@ -18,7 +18,7 @@ Starts all pods
#### **--latest**, **-l**
-Instead of providing the pod name or ID, start the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, start the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--pod-id-file**
diff --git a/docs/source/markdown/podman-pod-stats.1.md b/docs/source/markdown/podman-pod-stats.1.md
index 47d95983a..460571add 100644
--- a/docs/source/markdown/podman-pod-stats.1.md
+++ b/docs/source/markdown/podman-pod-stats.1.md
@@ -17,7 +17,7 @@ Show all containers. Only running containers are shown by default
#### **--latest**, **-l**
-Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--no-reset**
diff --git a/docs/source/markdown/podman-pod-stop.1.md b/docs/source/markdown/podman-pod-stop.1.md
index f2887b5a5..13d86d1db 100644
--- a/docs/source/markdown/podman-pod-stop.1.md
+++ b/docs/source/markdown/podman-pod-stop.1.md
@@ -23,7 +23,7 @@ ExecStop directive of a systemd service referencing that pod.
#### **--latest**, **-l**
-Instead of providing the pod name or ID, stop the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, stop the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--time**, **-t**=*seconds*
diff --git a/docs/source/markdown/podman-pod-top.1.md b/docs/source/markdown/podman-pod-top.1.md
index 42198c7fa..3f4c24117 100644
--- a/docs/source/markdown/podman-pod-top.1.md
+++ b/docs/source/markdown/podman-pod-top.1.md
@@ -17,7 +17,7 @@ Display the running processes of containers in a pod. The *format-descriptors* a
#### **--latest**, **-l**
-Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## FORMAT DESCRIPTORS
diff --git a/docs/source/markdown/podman-pod-unpause.1.md b/docs/source/markdown/podman-pod-unpause.1.md
index cd91a661b..ce883af69 100644
--- a/docs/source/markdown/podman-pod-unpause.1.md
+++ b/docs/source/markdown/podman-pod-unpause.1.md
@@ -17,7 +17,7 @@ Unpause all pods.
#### **--latest**, **-l**
-Instead of providing the pod name or ID, unpause the last created pod. (This option is not available with the remote Podman client)
+Instead of providing the pod name or ID, unpause the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-port.1.md b/docs/source/markdown/podman-port.1.md
index 2881cbb7b..a72fc12bf 100644
--- a/docs/source/markdown/podman-port.1.md
+++ b/docs/source/markdown/podman-port.1.md
@@ -21,7 +21,7 @@ or private ports/protocols as filters.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index 827fb2b2f..5b142d283 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -94,7 +94,7 @@ Print the n last created containers (all states)
#### **--latest**, **-l**
-Show the latest container created (all states) (This option is not available with the remote Podman client)
+Show the latest container created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--namespace**, **--ns**
diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md
index 6a1240269..00a86aa71 100644
--- a/docs/source/markdown/podman-pull.1.md
+++ b/docs/source/markdown/podman-pull.1.md
@@ -17,7 +17,7 @@ podman pull copies an image from a registry onto the local machine. The command
*IMPORTANT: Images are stored in local image storage.*
## SOURCE
-SOURCE is the location from the container image is pulled from. It supports all transports from **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport.
+SOURCE is the location from which the container image is pulled from. It supports all transports from **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, including Mac and Windows (excluding WSL2) machines, `docker` is the only supported transport.
```
# Pull from a container registry
@@ -63,7 +63,7 @@ Default is `${XDG\_RUNTIME\_DIR}/containers/auth.json`, which is set using `podm
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)** for details. (This option is not available with the remote Podman client)
+Please refer to **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)** for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--creds**=*[username[:password]]*
diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md
index 19c64a7e3..c71eecfd2 100644
--- a/docs/source/markdown/podman-push.1.md
+++ b/docs/source/markdown/podman-push.1.md
@@ -20,7 +20,7 @@ Images are pushed from those stored in local image storage.
## DESTINATION
- DESTINATION is the location the container image is pushed to. It supports all transports from `containers-transports(5)`. If no transport is specified, the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport.
+ DESTINATION is the location the container image is pushed to. It supports all transports from `containers-transports(5)`. If no transport is specified, the `docker` (i.e., container registry) transport is used. For remote clients, including Mac and Windows (excluding WSL2) machines, `docker` is the only supported transport.
```
# Push to a container registry
@@ -64,7 +64,7 @@ value can be entered. The password is entered without echo.
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d)
-Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
+Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--compress**
@@ -77,7 +77,7 @@ Specifies the compression format to use. Supported values are: `gzip`, `zstd` a
#### **--digestfile** *Digestfile*
-After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client)
+After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--disable-content-trust**
@@ -95,11 +95,11 @@ When writing the output image, suppress progress output
#### **--remove-signatures**
-Discard any pre-existing signatures in the image. (This option is not available with the remote Podman client)
+Discard any pre-existing signatures in the image. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--sign-by**=*key*
-Add a signature at the destination using the specified key. (This option is not available with the remote Podman client)
+Add a signature at the destination using the specified key. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--tls-verify**
diff --git a/docs/source/markdown/podman-remote.1.md b/docs/source/markdown/podman-remote.1.md
index 72c8d7226..e87129e38 100644
--- a/docs/source/markdown/podman-remote.1.md
+++ b/docs/source/markdown/podman-remote.1.md
@@ -57,18 +57,32 @@ URL to access Podman service (default from `containers.conf`, rootless "unix://r
- `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]`
Details:
- - `user` will default to either `root` or current running user
- - `password` has no default
- - `host` must be provided and is either the IP or name of the machine hosting the Podman service
- - `port` defaults to 22
- - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/<uid>/podman/podman.sock` if running rootless.
+ - `schema` is one of:
+ * `ssh` (default): a local unix(7) socket on the named `host` and `port`, reachable via SSH
+ * `tcp`: an unencrypted, unauthenticated TCP connection to the named `host` and `port`
+ * `unix`: a local unix(7) socket at the specified `path`, or the default for the user
+ - `user` will default to either `root` or the current running user (`ssh` only)
+ - `password` has no default (`ssh` only)
+ - `host` must be provided and is either the IP or name of the machine hosting the Podman service (`ssh` and `tcp`)
+ - `port` defaults to 22 (`ssh` and `tcp`)
+ - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/$UID/podman/podman.sock` if running rootless (`unix`), or must be explicitly specified (`ssh`)
URL value resolution precedence:
- command line value
- environment variable `CONTAINER_HOST`
- - `containers.conf`
+ - `containers.conf` `service_destinations` table
- `unix://run/podman/podman.sock`
+Remote connections use local containers.conf for default.
+
+Some example URL values in valid formats:
+ - unix://run/podman/podman.sock
+ - unix://run/user/$UID/podman/podman.sock
+ - ssh://notroot@localhost:22/run/user/$UID/podman/podman.sock
+ - ssh://root@localhost:22/run/podman/podman.sock
+ - tcp://localhost:34451
+ - tcp://127.0.0.1:34451
+
#### **--version**
Print the version
diff --git a/docs/source/markdown/podman-restart.1.md b/docs/source/markdown/podman-restart.1.md
index bb8f13a92..323087069 100644
--- a/docs/source/markdown/podman-restart.1.md
+++ b/docs/source/markdown/podman-restart.1.md
@@ -19,7 +19,7 @@ Restart all containers regardless of their current state.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--running**
Restart all containers that are already in the *running* state.
diff --git a/docs/source/markdown/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md
index f3807d2f7..23944270c 100644
--- a/docs/source/markdown/podman-rm.1.md
+++ b/docs/source/markdown/podman-rm.1.md
@@ -43,7 +43,7 @@ during the ExecStop directive of a systemd service referencing that container.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--time**, **-t**=*seconds*
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index efd60b46d..239cf3b83 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -43,7 +43,7 @@ pages.
## IMAGE
The image is specified using transport:path format. If no transport is specified, the `docker` (container registry)
-transport will be used by default. For remote Podman, `docker` is the only allowed transport.
+transport will be used by default. For remote Podman, including Mac and Windows (excluding WSL2) machines, `docker` is the only allowed transport.
**dir:**_path_
An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This
@@ -167,7 +167,7 @@ Write the container ID to *file*.
#### **--conmon-pidfile**=*file*
Write the pid of the **conmon** process to a file. As **conmon** runs in a separate process than Podman, this is necessary when using systemd to restart Podman containers.
-(This option is not available with the remote Podman client)
+(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--cpu-period**=*limit*
@@ -341,7 +341,7 @@ Set custom DNS servers. Invalid if using **--dns** with **--network** that is se
This option can be used to override the DNS
configuration passed to the container. Typically this is necessary when the
host DNS configuration is invalid for the container (e.g., **127.0.0.1**). When this
-is the case the **--dns** flags is necessary for every run.
+is the case the **--dns** flag is necessary for every run.
The special value **none** can be specified to disable creation of _/etc/resolv.conf_ in the container by Podman.
The _/etc/resolv.conf_ file in the image will be used without changes.
@@ -383,7 +383,7 @@ See [**Environment**](#environment) note below for precedence and examples.
#### **--env-host**
-Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client)
+Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--env-file**=*file*
@@ -411,7 +411,7 @@ Note: the **--gidmap** flag cannot be called in conjunction with the **--pod** f
#### **--group-add**=*group|keep-groups*
-Add additional groups to assign to primary user running within the container process.
+Assign additional groups to the primary user running within the container process.
- `keep-groups` is a special flag that tells Podman to keep the supplementary group access.
@@ -419,7 +419,7 @@ Allows container to use the user's supplementary group access. If file systems o
devices are only accessible by the rootless user's group, this flag tells the OCI
runtime to pass the group access into the container. Currently only available
with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups
-with this flag. (Not available for remote commands)
+with this flag. (Not available for remote commands, including Mac and Windows (excluding WSL2) machines)
#### **--health-cmd**=*"command"* | *'["command", "arg1", ...]'*
@@ -474,7 +474,7 @@ the container should not use any proxy. Proxy environment variables specified
for the container in any other way will override the values that would have
been passed through from the host. (Other ways to specify the proxy for the
container include passing the values with the **--env** flag, or hard coding the
-proxy environment at container build time.) (This option is not available with the remote Podman client)
+proxy environment at container build time.) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
Defaults to **true**.
@@ -548,7 +548,7 @@ $ podman info --format '{{ .Host.LogDriver }}'
journald
```
The **passthrough** driver passes down the standard streams (stdin, stdout, stderr) to the
-container. It is not allowed with the remote Podman client and on a tty, since it is
+container. It is not allowed with the remote Podman client, including Mac and Windows (excluding WSL2) machines, and on a tty, since it is
vulnerable to attacks via TIOCSTI.
@@ -722,7 +722,7 @@ Valid _mode_ values are:
- **alias=name**: Add network-scoped alias for the container.
- **ip=IPv4**: Specify a static ipv4 address for this container.
- **ip=IPv6**: Specify a static ipv6 address for this container.
- - **mac=MAC**: Specify a static mac address address for this container.
+ - **mac=MAC**: Specify a static mac address for this container.
- **interface_name**: Specify a name for the created network interface inside the container.
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
@@ -742,7 +742,7 @@ Valid _mode_ values are:
- **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only).
- **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to.
- **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
- Note: Rootlesskit changes the source IP address of incoming packets to a IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
+ Note: Rootlesskit changes the source IP address of incoming packets to an IP address in the container network namespace, usually `10.0.2.100`. If your application requires the real source IP address, e.g. web server logs, use the slirp4netns port handler. The rootlesskit port handler is also used for rootless containers when connected to user-defined networks.
- **port_handler=slirp4netns**: Use the slirp4netns port forwarding, it is slower than rootlesskit but preserves the correct source IP address. This port handler cannot be used for user-defined networks.
#### **--network-alias**=*alias*
@@ -767,6 +767,8 @@ This option conflicts with **--add-host**.
Whether to disable OOM Killer for the container or not.
+This flag is not supported on cgroups V2 systems.
+
#### **--oom-score-adj**=*num*
Tune the host's OOM preferences for containers (accepts values from **-1000** to **1000**).
@@ -816,7 +818,7 @@ If a container is run within a pod, and the pod has an infra-container, the infr
#### **--preserve-fds**=*N*
Pass down to the process N additional file descriptors (in addition to 0, 1, 2).
-The total FDs will be 3+N. (This option is not available with the remote Podman client)
+The total FDs will be 3+N. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--privileged**
@@ -1269,7 +1271,7 @@ The `--userns=auto` flag, requires that the user name `containers` and a range o
Example: `containers:2147483647:2147483648`.
-Podman allocates unique ranges of UIDs and GIDs from the `containers` subpordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
+Podman allocates unique ranges of UIDs and GIDs from the `containers` subordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
Valid `auto` options:
@@ -1307,7 +1309,7 @@ Create a bind mount. If you specify _/HOST-DIR_:_/CONTAINER-DIR_, Podman
bind mounts _host-dir_ in the host to _CONTAINER-DIR_ in the Podman
container. Similarly, _SOURCE-VOLUME_:_/CONTAINER-DIR_ will mount the volume
in the host to the container. If no such named volume exists, Podman will
-create one. (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.)
+create one. (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.)
The _options_ is a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup>
@@ -1377,7 +1379,7 @@ The **Z** option tells Podman to label the content with a private unshared label
Note: Do not relabel system files and directories. Relabeling system content
might cause other confined services on your machine to fail. For these types
-of containers we recommend that disable SELinux separation. The option
+of containers we recommend disabling SELinux separation. The option
`--security-opt label=disable` disables SELinux separation for the container.
For example if a user wanted to volume mount their entire home directory into a
container, they need to disable SELinux separation.
@@ -1394,6 +1396,10 @@ directory will be the lower, and the container storage directory will be the
upper. Modifications to the mount point are destroyed when the container
finishes executing, similar to a tmpfs mount point being unmounted.
+ For advanced users overlay option also supports custom non-volatile `upperdir` and `workdir`
+for the overlay mount. Custom `upperdir` and `workdir` can be fully managed by the users themselves
+and `podman` will not remove it on lifecycle completion. Example `:O,upperdir=/some/upper,workdir=/some/work`
+
Subsequent executions of the container will see the original source directory
content, any changes from previous container executions no longer exist.
@@ -1444,7 +1450,7 @@ the volume will not be able to change their privilege. By default volumes
are mounted with **nosuid**.
Mounting the volume with the **noexec** option means that no executables on the
-volume will be able to executed within the container.
+volume will be able to be executed within the container.
Mounting the volume with the **nodev** option means that no devices on the volume
will be able to be used by processes within the container. By default volumes
@@ -1515,7 +1521,7 @@ can override the working directory by using the **-w** option.
#### **--pidfile**=*path*
-When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client)
+When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile.
After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command:
@@ -1920,7 +1926,7 @@ $ podman run --network net1:ip=10.89.1.5 --network net2:ip=10.89.10.10 alpine ip
### Rootless Containers
-Podman runs as a non root user on most systems. This feature requires that a new enough version of **shadow-utils**
+Podman runs as a non-root user on most systems. This feature requires that a new enough version of **shadow-utils**
be installed. The **shadow-utils** package must include the **newuidmap**(1) and **newgidmap**(1) executables.
Note: RHEL7 and Centos 7 will not have this feature until RHEL7.7 is released.
diff --git a/docs/source/markdown/podman-start.1.md b/docs/source/markdown/podman-start.1.md
index b8ed181e0..793f27aa4 100644
--- a/docs/source/markdown/podman-start.1.md
+++ b/docs/source/markdown/podman-start.1.md
@@ -32,7 +32,7 @@ Attach container's STDIN. The default is false.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--sig-proxy**
diff --git a/docs/source/markdown/podman-stats.1.md b/docs/source/markdown/podman-stats.1.md
index bbb4bcb06..a1a156b10 100644
--- a/docs/source/markdown/podman-stats.1.md
+++ b/docs/source/markdown/podman-stats.1.md
@@ -27,7 +27,7 @@ Show all containers. Only running containers are shown by default
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--no-reset**
@@ -98,6 +98,12 @@ ID NAME MEM USAGE / LIMIT
6eae9e25a564 clever_bassi 3.031MB / 16.7GB
```
+Note: When using a slirp4netns network with the rootlesskit port
+handler, the traffic send via the port forwarding will be accounted to
+the `lo` device. Traffic accounted to `lo` is not accounted in the
+stats output.
+
+
## SEE ALSO
**[podman(1)](podman.1.md)**
diff --git a/docs/source/markdown/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md
index 9a852cbae..e35ab9182 100644
--- a/docs/source/markdown/podman-stop.1.md
+++ b/docs/source/markdown/podman-stop.1.md
@@ -34,7 +34,7 @@ during the ExecStop directive of a systemd service referencing that container.
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
#### **--time**, **-t**=*seconds*
diff --git a/docs/source/markdown/podman-system-prune.1.md b/docs/source/markdown/podman-system-prune.1.md
index d8b218db2..fb9ed44d6 100644
--- a/docs/source/markdown/podman-system-prune.1.md
+++ b/docs/source/markdown/podman-system-prune.1.md
@@ -22,16 +22,18 @@ Recursively remove all unused pod, container, image and volume data (Maximum 50
Provide filter values.
-The --filter flag format is of “key=value”. If there is more than one filter, then pass multiple flags (e.g., --filter "foo=bar" --filter "bif=baz")
+The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*.
Supported filters:
-- `until` (_timestamp_) - only remove containers and images created before given timestamp
-- `label` (label=_key_, label=_key=value_, label!=_key_, or label!=_key=value_) - only remove containers and images, with (or without, in case label!=... is used) the specified labels.
+| Filter | Description |
+| :----------------: | --------------------------------------------------------------------------- |
+| *label* | Only remove containers and images, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *until* | Only remove containers and images created before given timestamp. |
-The until filter can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes containers and images with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes containers and images without the specified labels.
-The label filter accepts two formats. One is the label=... (label=_key_ or label=_key=value_), which removes containers and images with the specified labels. The other format is the label!=... (label!=_key_ or label!=_key=value_), which removes containers and images without the specified labels.
+The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
#### **--force**, **-f**
diff --git a/docs/source/markdown/podman-system-reset.1.md b/docs/source/markdown/podman-system-reset.1.md
index 90bcb5f53..c463481e6 100644
--- a/docs/source/markdown/podman-system-reset.1.md
+++ b/docs/source/markdown/podman-system-reset.1.md
@@ -7,7 +7,7 @@ podman\-system\-reset - Reset storage back to initial state
**podman system reset** [*options*]
## DESCRIPTION
-**podman system reset** removes all pods, containers, images and volumes.
+**podman system reset** removes all pods, containers, images, networks and volumes.
This command must be run **before** changing any of the following fields in the
`containers.conf` or `storage.conf` files: `driver`, `static_dir`, `tmp_dir`
@@ -28,6 +28,17 @@ Print usage statement
## EXAMPLES
+```
+$ podman system reset
+WARNING! This will remove:
+ - all containers
+ - all pods
+ - all images
+ - all networks
+ - all build cache
+Are you sure you want to continue? [y/N] y
+```
+
### Switching rootless user from VFS driver to overlay with fuse-overlayfs
If the user ran rootless containers without having the `fuse-overlayfs` program
diff --git a/docs/source/markdown/podman-top.1.md b/docs/source/markdown/podman-top.1.md
index d385cde28..6b9433b89 100644
--- a/docs/source/markdown/podman-top.1.md
+++ b/docs/source/markdown/podman-top.1.md
@@ -20,7 +20,7 @@ Print usage statement
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods.(This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods.(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## FORMAT DESCRIPTORS
diff --git a/docs/source/markdown/podman-unmount.1.md b/docs/source/markdown/podman-unmount.1.md
index 045ea5456..692b1e495 100644
--- a/docs/source/markdown/podman-unmount.1.md
+++ b/docs/source/markdown/podman-unmount.1.md
@@ -43,7 +43,7 @@ as the mount point could be removed without their knowledge.
Instead of providing the container name or ID, use the last created container.
If you use methods other than Podman to run containers such as CRI-O, the last
-started container could be from either of those methods. (This option is not available with the remote Podman client)
+started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLE
diff --git a/docs/source/markdown/podman-untag.1.md b/docs/source/markdown/podman-untag.1.md
index 8314e5f9b..0dd882a92 100644
--- a/docs/source/markdown/podman-untag.1.md
+++ b/docs/source/markdown/podman-untag.1.md
@@ -9,7 +9,7 @@ podman\-untag - Removes one or more names from a locally-stored image
**podman image untag** *image* [*name*[:*tag*]...]
## DESCRIPTION
-Remove one or more names from an image in the local storage. The image can be referred to by ID or reference. If a no name is specified, all names are removed the image. If a specified name is a short name and does not include a registry `localhost/` will be prefixed (e.g., `fedora` -> `localhost/fedora`). If a specified name does not include a tag `:latest` will be appended (e.g., `localhost/fedora` -> `localhost/fedora:latest`).
+Remove one or more names from an image in the local storage. The image can be referred to by ID or reference. If no name is specified, all names are removed from the image. If a specified name is a short name and does not include a registry, `localhost/` will be prefixed (e.g., `fedora` -> `localhost/fedora`). If a specified name does not include a tag, `:latest` will be appended (e.g., `localhost/fedora` -> `localhost/fedora:latest`).
## OPTIONS
diff --git a/docs/source/markdown/podman-volume-exists.1.md b/docs/source/markdown/podman-volume-exists.1.md
index dbdf0985c..28d42e987 100644
--- a/docs/source/markdown/podman-volume-exists.1.md
+++ b/docs/source/markdown/podman-volume-exists.1.md
@@ -28,7 +28,7 @@ $ echo $?
$
```
-Check if an volume called `mysql` exists (the volume does not actually exist).
+Check if a volume called `mysql` exists (the volume does not actually exist).
```
$ podman volume exists mysql
$ echo $?
diff --git a/docs/source/markdown/podman-volume-prune.1.md b/docs/source/markdown/podman-volume-prune.1.md
index 012567957..2028e42f2 100644
--- a/docs/source/markdown/podman-volume-prune.1.md
+++ b/docs/source/markdown/podman-volume-prune.1.md
@@ -21,12 +21,20 @@ Do not prompt for confirmation.
#### **--filter**
-Filter volumes to be pruned. Volumes can be filtered by the following attributes:
+Provide filter values.
-| **Filter** | **Description** |
-| ---------- | ------------------------------------------------------------------------------------- |
-| label | [Key] or [Key=Value] Label assigned to a volume |
-| until | Only remove volumes created before given timestamp |
+The *filters* argument format is of `key=value`. If there is more than one *filter*, then pass multiple OPTIONS: **--filter** *foo=bar* **--filter** *bif=baz*.
+
+Supported filters:
+
+| Filter | Description |
+| :----------------: | --------------------------------------------------------------------------- |
+| *label* | Only remove volumes, with (or without, in the case of label!=[...] is used) the specified labels. |
+| *until* | Only remove volumes created before given timestamp. |
+
+The `label` *filter* accepts two formats. One is the `label`=*key* or `label`=*key*=*value*, which removes volumes with the specified labels. The other format is the `label!`=*key* or `label!`=*key*=*value*, which removes volumes without the specified labels.
+
+The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time.
#### **--help**
diff --git a/docs/source/markdown/podman-wait.1.md b/docs/source/markdown/podman-wait.1.md
index 7ee53c57e..e307e4528 100644
--- a/docs/source/markdown/podman-wait.1.md
+++ b/docs/source/markdown/podman-wait.1.md
@@ -29,7 +29,7 @@ Condition to wait on (default "stopped")
#### **--latest**, **-l**
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
-to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client)
+to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines)
## EXAMPLES
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index c1a22c0c1..a77e1ecbd 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -32,11 +32,16 @@ The CGroup manager to use for container cgroups. Supported values are cgroupfs o
Note: Setting this flag can cause certain commands to break when called on containers previously created by the other CGroup manager type.
Note: CGroup manager is not supported in rootless mode when using CGroups Version V1.
-#### **--cni-config-dir**
-Path of the configuration directory for CNI networks. (Default: `/etc/cni/net.d`)
+#### **--network-config-dir**=*directory*
+
+Path to the directory where network configuration files are located.
+For the CNI backend the default is "/etc/cni/net.d" as root
+and "$HOME/.config/cni/net.d" as rootless.
+For the netavark backend "/etc/containers/networks" is used as root
+and "$graphroot/networks" as rootless.
#### **--connection**, **-c**
-Connection to use for remote podman (Default connection is configured in `containers.conf`)
+Connection to use for remote podman, including Mac and Windows (excluding WSL2) machines, (Default connection is configured in `containers.conf`)
Remote connections use local containers.conf for default.
#### **--conmon**
@@ -96,11 +101,10 @@ Path to the command binary to use for setting up a network. It is currently onl
Redirect stdout to /dev/null. This command will prevent all stdout from the Podman command. The **--noout** option will not block stderr or stdout from containers.
-
#### **--remote**, **-r**
When true, access to the Podman service will be remote. Defaults to false.
Settings can be modified in the containers.conf file. If the CONTAINER_HOST
-environment variable is set, the remote option defaults to true.
+environment variable is set, the **--remote** option defaults to true.
#### **--url**=*value*
URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`).
@@ -108,19 +112,32 @@ URL to access Podman service (default from `containers.conf`, rootless `unix://r
- `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]`
Details:
- - `user` will default to either `root` or current running user
- - `password` has no default
- - `host` must be provided and is either the IP or name of the machine hosting the Podman service
- - `port` defaults to 22
- - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/<uid>/podman/podman.sock` if running rootless.
+ - `schema` is one of:
+ * `ssh` (default): a local unix(7) socket on the named `host` and `port`, reachable via SSH
+ * `tcp`: an unencrypted, unauthenticated TCP connection to the named `host` and `port`
+ * `unix`: a local unix(7) socket at the specified `path`, or the default for the user
+ - `user` will default to either `root` or the current running user (`ssh` only)
+ - `password` has no default (`ssh` only)
+ - `host` must be provided and is either the IP or name of the machine hosting the Podman service (`ssh` and `tcp`)
+ - `port` defaults to 22 (`ssh` and `tcp`)
+ - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/$UID/podman/podman.sock` if running rootless (`unix`), or must be explicitly specified (`ssh`)
URL value resolution precedence:
- command line value
- environment variable `CONTAINER_HOST`
- - `containers.conf`
+ - `containers.conf` `service_destinations` table
- `unix://run/podman/podman.sock`
+
Remote connections use local containers.conf for default.
+Some example URL values in valid formats:
+ - unix://run/podman/podman.sock
+ - unix://run/user/$UID/podman/podman.sock
+ - ssh://notroot@localhost:22/run/user/$UID/podman/podman.sock
+ - ssh://root@localhost:22/run/podman/podman.sock
+ - tcp://localhost:34451
+ - tcp://127.0.0.1:34451
+
#### **--root**=*value*
Storage root dir in which data, including images, is stored (default: "/var/lib/containers/storage" for UID 0, "$HOME/.local/share/containers/storage" for other users).
@@ -162,7 +179,7 @@ Storage driver option, Default storage driver options are configured in /etc/con
Output logging information to syslog as well as the console (default *false*).
-On remote clients, logging is directed to the file $HOME/.config/containers/podman.log.
+On remote clients, including Mac and Windows (excluding WSL2) machines, logging is directed to the file $HOME/.config/containers/podman.log.
#### **--tmpdir**
@@ -212,7 +229,7 @@ Set default `--storage-opts` value.
#### **TMPDIR**
-Set the the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`.
+Set the temporary storage location of downloaded container images. Podman defaults to use `/var/tmp`.
#### **XDG_CONFIG_HOME**
@@ -368,7 +385,7 @@ The storage configuration file specifies all of the available container storage
When Podman runs in rootless mode, the file `$HOME/.config/containers/storage.conf` is used instead of the system defaults.
-If the **CONTAINERS_STORAGE_CONF** environment variable is set, the its value is used for the storage.conf file rather than the default.
+If the **CONTAINERS_STORAGE_CONF** environment variable is set, then its value is used for the storage.conf file rather than the default.
## Rootless mode
Podman can also be used as non-root user. When podman runs in rootless mode, a user namespace is automatically created for the user, defined in /etc/subuid and /etc/subgid.
diff --git a/go.mod b/go.mod
index e1dab0732..fbfa7a90e 100644
--- a/go.mod
+++ b/go.mod
@@ -5,36 +5,36 @@ go 1.16
require (
github.com/BurntSushi/toml v1.0.0
github.com/blang/semver v3.5.1+incompatible
- github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
+ github.com/buger/goterm v1.0.1
github.com/checkpoint-restore/checkpointctl v0.0.0-20211204171957-54b4ebfdb681
github.com/checkpoint-restore/go-criu/v5 v5.3.0
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20220111162300-46367ec063fd
github.com/containernetworking/cni v1.0.1
github.com/containernetworking/plugins v1.0.1
- github.com/containers/buildah v1.23.1-0.20220112160421-d744ebc4b1d5
- github.com/containers/common v0.46.1-0.20220117145719-da777f8b15b1
+ github.com/containers/buildah v1.24.1
+ github.com/containers/common v0.47.3
github.com/containers/conmon v2.0.20+incompatible
- github.com/containers/image/v5 v5.18.0
+ github.com/containers/image/v5 v5.19.1
github.com/containers/ocicrypt v1.1.2
- github.com/containers/psgo v1.7.1
- github.com/containers/storage v1.37.1-0.20211213220314-73a749e4fec5
+ github.com/containers/psgo v1.7.2
+ github.com/containers/storage v1.38.2
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3
github.com/davecgh/go-spew v1.1.1
- github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f
+ github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v20.10.12+incompatible
- github.com/docker/go-connections v0.4.0
- github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc
+ github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
+ github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
github.com/docker/go-units v0.4.0
github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
github.com/fsnotify/fsnotify v1.5.1
github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.6
- github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/google/uuid v1.3.0
- github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
+ github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/hashicorp/go-multierror v1.1.1
@@ -44,12 +44,12 @@ require (
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/mrunalp/fileutils v0.5.0
github.com/onsi/ginkgo v1.16.5
- github.com/onsi/gomega v1.17.0
+ github.com/onsi/gomega v1.18.1
github.com/opencontainers/go-digest v1.0.0
- github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1
+ github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198
github.com/opencontainers/runc v1.1.0
- github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
- github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7
+ github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab
+ github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f
github.com/opencontainers/selinux v1.10.0
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
@@ -62,11 +62,11 @@ require (
github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/ulikunitz/xz v0.5.10
github.com/vbauerster/mpb/v6 v6.0.4
- github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
+ github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4
go.etcd.io/bbolt v1.3.6
- golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
+ golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
- golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
golang.org/x/text v0.3.7
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
diff --git a/go.sum b/go.sum
index 65401fe34..85cb7baa9 100644
--- a/go.sum
+++ b/go.sum
@@ -107,13 +107,16 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
-github.com/Microsoft/hcsshim v0.9.1 h1:VfDCj+QnY19ktX5TsH22JHcjaZ05RWQiwDbOyEg5ziM=
-github.com/Microsoft/hcsshim v0.9.1/go.mod h1:Y/0uV2jUab5kBI7SQgl62at0AVX7uaruzADAVmxm3eM=
+github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY=
+github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
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/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
+github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
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=
@@ -124,6 +127,7 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
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/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -133,6 +137,7 @@ github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY
github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE=
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
@@ -142,6 +147,7 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI=
github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU=
@@ -160,15 +166,17 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI=
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=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
-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/goterm v1.0.1 h1:kSgw3jcjYUzC0Uh/eG8ULjccuz353solup27lUH8Zug=
+github.com/buger/goterm v1.0.1/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
@@ -288,8 +296,9 @@ github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oM
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
-github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng=
github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0 h1:t0IW5kOmY7AXDAWRUs2uVzDhijAUOAYVr/dyRhOQvBg=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -314,16 +323,14 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
github.com/containernetworking/plugins v1.0.1 h1:wwCfYbTCj5FC0EJgyzyjTXmqysOiJE9r712Z+2KVZAk=
github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
-github.com/containers/buildah v1.23.1-0.20220112160421-d744ebc4b1d5 h1:J4ZMQgpzjClLNuRDCIYDY2KZE1yO9A1I3A/jEaFvtaY=
-github.com/containers/buildah v1.23.1-0.20220112160421-d744ebc4b1d5/go.mod h1:pA9nL58rY+rtoyZkzPmkv02Nwb9ifvYlChg95gKkNAY=
-github.com/containers/common v0.46.1-0.20220110165509-08c2c97e5e25/go.mod h1:hXUU9gtA8V9dSLHhizp/k/s0ZXBzrnUSScUfrsw8z2Y=
-github.com/containers/common v0.46.1-0.20220117145719-da777f8b15b1 h1:TGXTygk3STL+G4F1zGgSITdIEE5i+BgsSDLOmGuUYTY=
-github.com/containers/common v0.46.1-0.20220117145719-da777f8b15b1/go.mod h1:lJkY5VdkdU2BEDdbO5vgi3G69KWEgWBWXi6tNgm2BlM=
+github.com/containers/buildah v1.24.1 h1:PlvU0hbUsm1x4H9kPcsmqjViqDGnBpSZT3QtZ00RtgI=
+github.com/containers/buildah v1.24.1/go.mod h1:sE7AaoPQYwAB7dleOOKOpzOO3bA8lRUvZRiZcn/RYi0=
+github.com/containers/common v0.47.3 h1:pRT7gkLrBSQe3075j5hoHYeeKpGTWBJHws+tS5xxfak=
+github.com/containers/common v0.47.3/go.mod h1:/VAV4ibC27Lfyb9cxXM4uTYrJFa/7s+utNB052MJdzY=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
-github.com/containers/image/v5 v5.17.1-0.20220106205022-73f80d60f0e1/go.mod h1:daAiRXgcGIf/7eD7B2EkuHHw084/8M8Kh35rzOu56y0=
-github.com/containers/image/v5 v5.18.0 h1:YbvpXl5zd6IbZnt4XiOU0+c24xBQAQL9q3/e5kyk19k=
-github.com/containers/image/v5 v5.18.0/go.mod h1:ybujPwS7YEAPhLXJ3vvZGdKftk+sPSvp/djg9qTPvro=
+github.com/containers/image/v5 v5.19.1 h1:g4/+XIuh1kRoRn2MfLDhfHhkNOIO9JtqhSyo55tjpfE=
+github.com/containers/image/v5 v5.19.1/go.mod h1:ewoo3u+TpJvGmsz64XgzbyTHwHtM94q7mgK/pX+v2SE=
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 v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
@@ -331,13 +338,12 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/psgo v1.7.1 h1:2N6KADeFvBm1aI2iXxu6+/Xh7CCkdh8p8F3F/cpIU5I=
-github.com/containers/psgo v1.7.1/go.mod h1:mWGpFzW73qWFA+blhF6l7GuKzbrACkYgr/ajiNQR+RM=
+github.com/containers/psgo v1.7.2 h1:WbCvsY9w+nCv3j4der0mbD3PSRUv/W8l+G0YrZrdSDc=
+github.com/containers/psgo v1.7.2/go.mod h1:SLpqxsPOHtTqRygjutCPXmeU2PoEFzV3gzJplN4BMx0=
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
-github.com/containers/storage v1.37.1-0.20211119174841-bf170b3ddac0/go.mod h1:XjCNlt5JUUmRuTJXhFxHb9hHGPho7DNg3o4N/14prdQ=
-github.com/containers/storage v1.37.1-0.20211122164443-82b8f06bfc08/go.mod h1:hvKpaiPRALDI7oz4Jx+AEch8iS/viRnc22HPilQROWU=
-github.com/containers/storage v1.37.1-0.20211213220314-73a749e4fec5 h1:DOpYQGCHIJfrErey3FyondnZGfZrbfGpHAN6nQssE1o=
-github.com/containers/storage v1.37.1-0.20211213220314-73a749e4fec5/go.mod h1:5qRpx96WJRTCQCsArfrWjUh398JSNCaTJG6RbOhMlqY=
+github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc=
+github.com/containers/storage v1.38.2 h1:8bAIxnVBGKzMw5EWCivVj24bztQT6IkDp4uHiyhnzwE=
+github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ=
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=
@@ -388,8 +394,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 h1:j6vGflaQ2T7yOWqVgPdiRF73j/U2Zmpbbzab8nyDCRQ=
github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1/go.mod h1:QS1XzqZLcDniNYrN7EZefq3wIyb/M2WmJbql4ZKoc1Q=
-github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f h1:N2HvbwONtcvzegFxOAgGt15JsajIk5QzY3j5X3VzFDI=
-github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
+github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001 h1:WAg57gnaAWWjMAELcwHjc2xy0PoXQ5G+vn3+XS6s1jI=
+github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8=
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
@@ -404,15 +410,16 @@ github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
-github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q=
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
-github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc h1:/A+mPcpajLsWiX9gSnzdVKM/IzZoYiNqXHe83z50k2c=
-github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
+github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 h1:YcvzLmdrP/b8kLAGJ8GT7bdncgCAiWxJZIlt84D+RJg=
+github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 h1:moehPjPiGUaWdwgOl92xRyFHJyaqXDHcCyW9M6nmCK4=
@@ -429,6 +436,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
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/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -452,6 +460,9 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -467,7 +478,13 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/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/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
+github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -620,8 +637,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
-github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw=
github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -642,8 +659,9 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
-github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
+github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
+github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -743,11 +761,13 @@ github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5y
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4=
github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
-github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
-github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
+github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -777,6 +797,8 @@ github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSg
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -786,8 +808,10 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
+github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -797,6 +821,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
@@ -818,6 +843,7 @@ github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
+github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -829,6 +855,7 @@ github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GW
github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
+github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -899,6 +926,7 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
@@ -927,8 +955,6 @@ github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinK
github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s=
github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
-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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -938,7 +964,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE=
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/exhaustive v0.2.3/go.mod h1:bhIX678Nx8inLM9PbpvK1yv6oGtoP8BfaIeMzgBNKvc=
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
@@ -976,8 +1001,8 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202193544-a5463b7f9c84/go.mod h1:Qnt1q4cjDNQI9bT832ziho5Iw2BhK8o1KwLOwW56VP4=
-github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1 h1:R0VgKjcNQhH6AKteTyHcdoTgGRGEYZhXT05Gv1LJLh4=
-github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q=
+github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 h1:+czc/J8SlhPKLOtVLMQc+xDCFBT73ZStMsRhSsUhsSg=
+github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/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.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -992,13 +1017,15 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
+github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab h1:YQZXa3elcHgKXAa2GjVFC9M3JeP7ZPyFD1YByDx/dgQ=
+github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
-github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7 h1:6JHkPc2wUOsj2XBpYzyvmCL5Y/fA3TFaomYv/Iggt1g=
-github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
+github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f h1:MMcsVl0FAVEahmXTy+uXoDTw3yJq7nGrK8ITs/kkreo=
+github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f/go.mod h1:/tgP02fPXGHkU3/qKK1Y0Db4yqNyGm03vLq/mzHzcS4=
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
@@ -1006,8 +1033,8 @@ github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4=
-github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
+github.com/openshift/imagebuilder v1.2.2 h1:++jWWMkTVJKP2MIjTPaTk2MqwWIOYYlDaQbZyLlLBh0=
+github.com/openshift/imagebuilder v1.2.2/go.mod h1:TRYHe4CH9U6nkDjxjBNM5klrLbJBrRbpJE5SaRwUBsQ=
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=
@@ -1038,6 +1065,8 @@ github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:w
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
+github.com/proglottis/gpgme v0.1.1 h1:72xI0pt/hy7pqsRxk32KExITkXp+RZErRizsA+up/lQ=
+github.com/proglottis/gpgme v0.1.1/go.mod h1:fPbW/EZ0LvwQtH8Hy7eixhp1eF3G39dtx7GUN+0Gmy0=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
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=
@@ -1109,12 +1138,16 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
+github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
@@ -1185,6 +1218,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/sylabs/release-tools v0.1.0/go.mod h1:pqP/z/11/rYMQ0OM/Nn7TxGijw7KfZwW9UolD/J1TUo=
+github.com/sylabs/sif/v2 v2.3.1 h1:NHoc/rZpnOS05etmT+j8IJOZP2Cc8zHHG8rKSVosvZs=
+github.com/sylabs/sif/v2 v2.3.1/go.mod h1:NnvveH62GiibimL00MrI6YYcZfb7DnZMcRo/40giY+0=
github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -1217,6 +1253,7 @@ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o
github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.19.1/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/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@@ -1231,14 +1268,15 @@ github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlI
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
github.com/vbauerster/mpb/v6 v6.0.4 h1:h6J5zM/2wimP5Hj00unQuV8qbo5EPcj6wbkCqgj7KcY=
github.com/vbauerster/mpb/v6 v6.0.4/go.mod h1:a/+JT57gqh6Du0Ay5jSR+uBMfXGdlR7VQlGP52fJxLM=
-github.com/vbauerster/mpb/v7 v7.3.0 h1:WwRtHHT26gjVln0yJypDEEpTWyX9sk4QcUxM6tQjdEc=
-github.com/vbauerster/mpb/v7 v7.3.0/go.mod h1:KERDXx9bfuStUwTH2FbsrJhJhVu1q+xmjjoCZMZrin4=
+github.com/vbauerster/mpb/v7 v7.3.2 h1:tCuxMy8G9cLdjb61b6wO7I1vRT/LyMEzRbr3xCC0JPU=
+github.com/vbauerster/mpb/v7 v7.3.2/go.mod h1:wfxIZcOJq/bG1/lAtfzMXcOiSvbqVi/5GX5WCSi+IsA=
github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
-github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA=
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
+github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4 h1:fB26rIBlWTVJyEB6ONHdoEvUbvwoudH0/cMEXHiD1RU=
+github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
@@ -1246,6 +1284,8 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvV
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -1314,6 +1354,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1327,11 +1368,14 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
+golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1421,6 +1465,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
@@ -1430,10 +1475,11 @@ golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1558,9 +1604,11 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1572,7 +1620,6 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1580,6 +1627,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211001092434-39dca1131b70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1587,8 +1635,9 @@ golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
@@ -1836,7 +1885,6 @@ google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
@@ -1877,7 +1925,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
@@ -1901,8 +1948,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
diff --git a/hack/bats b/hack/bats
index cd81a9c73..ca9835a1f 100755
--- a/hack/bats
+++ b/hack/bats
@@ -6,18 +6,21 @@
###############################################################################
# BEGIN usage message
-usage="Usage: $0 [--root] [--rootless] [--filter=filename[:testname]]
+usage="Usage: $0 [--root] [--rootless] [FILENAME-PATTERN[:TEST-PATTERN]]
$0 is a wrapper for invoking podman system tests.
--root Run only as root
--rootless Run only as user (i.e. you)
- --filter=name Run only test files that match 'test/system/*name*',
- e.g. '500' or 'net' will match 500-networking.bats.
- If ':pattern' is appended, and you have a modern-enough
- version of bats installed, runs with '--filter pattern'
- which runs only subtests that match 'pattern'
+ FILENAME-PATTERN Run only test files that match 'test/system/*name*',
+ e.g. '500' or 'net' will match 500-networking.bats.
+
+ TEST-PATTERN When appended to a filename-pattern, and you have a
+ modern-enough version of bats installed (i.e. Fedora
+ but not RHEL), runs with '--filter TEST-PATTERN' which
+ runs only subtests within FILENAME-PATTERH whose names
+ match that string.
-T Passed on to bats, which will then show timing data
@@ -98,6 +101,9 @@ if [[ -z "$CONTAINERS_HELPER_BINARY_DIR" ]]; then
export CONTAINERS_HELPER_BINARY_DIR=$(pwd)/bin
fi
+# Used in 120-load test to identify rootless destination for podman image scp
+export PODMAN_ROOTLESS_USER=$(id -un)
+
# Root
if [ -z "$ROOTLESS_ONLY" ]; then
echo "# bats ${bats_filter[@]} $TESTS"
@@ -105,6 +111,7 @@ if [ -z "$ROOTLESS_ONLY" ]; then
--preserve-env=PODMAN_TEST_DEBUG \
--preserve-env=OCI_RUNTIME \
--preserve-env=CONTAINERS_HELPER_BINARY_DIR \
+ --preserve-env=PODMAN_ROOTLESS_USER \
bats "${bats_opts[@]}" "${bats_filter[@]}" $TESTS
rc=$?
fi
diff --git a/hack/get_ci_vm.sh b/hack/get_ci_vm.sh
index 1a4804857..ef7069a81 100755
--- a/hack/get_ci_vm.sh
+++ b/hack/get_ci_vm.sh
@@ -47,11 +47,10 @@ elif [[ "$1" == "--setup" ]]; then
cd $REPO_DIRPATH
echo "+ Loading ./contrib/cirrus/lib.sh" > /dev/stderr
source ./contrib/cirrus/lib.sh
- echo "+ Mimicking .cirrus.yml clone_script and build_task" > /dev/stderr
+ echo "+ Mimicking .cirrus.yml build_task" > /dev/stderr
make install.tools
- make vendor
- make podman
- make podman-remote
+ make binaries
+ make docs
echo "+ Running environment setup" > /dev/stderr
./contrib/cirrus/setup_environment.sh
else
diff --git a/hack/podman-socat b/hack/podman-socat
index 6ee6b89d8..28fbb6864 100755
--- a/hack/podman-socat
+++ b/hack/podman-socat
@@ -95,7 +95,7 @@ EOT
PODMAN_ARGS="--storage-driver=vfs \
--root=${TMPDIR}/crio \
--runroot=${TMPDIR}/crio-run \
- --cni-config-dir=$CNI_CONFIG_PATH \
+ --network-config-dir=$CNI_CONFIG_PATH \
--cgroup-manager=systemd \
"
if [[ -n $VERBOSE ]]; then
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 7d4e28d5d..d1c190905 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/storage/pkg/stringid"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
)
// ExecConfig contains the configuration of an exec session
@@ -774,13 +775,40 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
return exitCode, nil
}
-// cleanup an exec session after its done
-func (c *Container) cleanupExecBundle(sessionID string) error {
- if err := os.RemoveAll(c.execBundlePath(sessionID)); err != nil && !os.IsNotExist(err) {
- return err
+// cleanupExecBundle cleanups an exec session after its done
+// Please be careful when using this function since it might temporarily unlock
+// the container when os.RemoveAll($bundlePath) fails with ENOTEMPTY or EBUSY
+// errors.
+func (c *Container) cleanupExecBundle(sessionID string) (Err error) {
+ path := c.execBundlePath(sessionID)
+ for attempts := 0; attempts < 50; attempts++ {
+ Err = os.RemoveAll(path)
+ if Err == nil || os.IsNotExist(Err) {
+ return nil
+ }
+ if pathErr, ok := Err.(*os.PathError); ok {
+ Err = pathErr.Err
+ if errors.Cause(Err) == unix.ENOTEMPTY || errors.Cause(Err) == unix.EBUSY {
+ // give other processes a chance to use the container
+ if !c.batched {
+ if err := c.save(); err != nil {
+ return err
+ }
+ c.lock.Unlock()
+ }
+ time.Sleep(time.Millisecond * 100)
+ if !c.batched {
+ c.lock.Lock()
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+ }
+ return
}
-
- return nil
+ return
}
// the path to a containers exec session bundle
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 5389d05a4..1344fc659 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -274,7 +274,7 @@ func (c *Container) GetInspectMounts(namedVolumes []*ContainerNamedVolume, image
return inspectMounts, nil
}
-// GetSecurityOptions retrives and returns the security related annotations and process information upon inspection
+// GetSecurityOptions retrieves and returns the security related annotations and process information upon inspection
func (c *Container) GetSecurityOptions() []string {
ctrSpec := c.config.Spec
SecurityOpt := []string{}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 84293ccb2..86d8586d0 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -391,18 +391,52 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
overlayFlag := false
+ upperDir := ""
+ workDir := ""
for _, o := range namedVol.Options {
if o == "O" {
overlayFlag = true
}
+ if overlayFlag && strings.Contains(o, "upperdir") {
+ splitOpt := strings.SplitN(o, "=", 2)
+ if len(splitOpt) > 1 {
+ upperDir = splitOpt[1]
+ if upperDir == "" {
+ return nil, errors.New("cannot accept empty value for upperdir")
+ }
+ }
+ }
+ if overlayFlag && strings.Contains(o, "workdir") {
+ splitOpt := strings.SplitN(o, "=", 2)
+ if len(splitOpt) > 1 {
+ workDir = splitOpt[1]
+ if workDir == "" {
+ return nil, errors.New("cannot accept empty value for workdir")
+ }
+ }
+ }
}
if overlayFlag {
+ var overlayMount spec.Mount
+ var overlayOpts *overlay.Options
contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID())
if err != nil {
return nil, err
}
- overlayMount, err := overlay.Mount(contentDir, mountPoint, namedVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions())
+
+ if (upperDir != "" && workDir == "") || (upperDir == "" && workDir != "") {
+ return nil, errors.Wrapf(err, "must specify both upperdir and workdir")
+ }
+
+ overlayOpts = &overlay.Options{RootUID: c.RootUID(),
+ RootGID: c.RootGID(),
+ UpperDirOptionFragment: upperDir,
+ WorkDirOptionFragment: workDir,
+ GraphOpts: c.runtime.store.GraphOptions(),
+ }
+
+ overlayMount, err = overlay.MountWithOptions(contentDir, mountPoint, namedVol.Dest, overlayOpts)
if err != nil {
return nil, errors.Wrapf(err, "mounting overlay failed %q", mountPoint)
}
@@ -476,6 +510,9 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if c.IsReadOnly() && dstPath != "/dev/shm" {
newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev")
}
+ if dstPath == "/dev/shm" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir {
+ newMount.Options = append(newMount.Options, "nosuid", "noexec", "nodev")
+ }
if !MountExists(g.Mounts(), dstPath) {
g.AddMount(newMount)
} else {
@@ -1536,6 +1573,9 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if c.IsReadOnly() && dstPath != "/dev/shm" {
newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev")
}
+ if dstPath == "/dev/shm" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir {
+ newMount.Options = append(newMount.Options, "nosuid", "noexec", "nodev")
+ }
if !MountExists(g.Mounts(), dstPath) {
g.AddMount(newMount)
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 110f37b91..f490ac626 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -834,21 +834,25 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
return nil
}
-func getContainerNetNS(ctr *Container) (string, error) {
+func getContainerNetNS(ctr *Container) (string, *Container, error) {
if ctr.state.NetNS != nil {
- return ctr.state.NetNS.Path(), nil
+ return ctr.state.NetNS.Path(), nil, nil
}
if ctr.config.NetNsCtr != "" {
c, err := ctr.runtime.GetContainer(ctr.config.NetNsCtr)
if err != nil {
- return "", err
+ return "", nil, err
}
if err = c.syncContainer(); err != nil {
- return "", err
+ return "", c, err
}
- return getContainerNetNS(c)
+ netNs, c2, err := getContainerNetNS(c)
+ if c2 != nil {
+ c = c2
+ }
+ return netNs, c, err
}
- return "", nil
+ return "", nil, nil
}
// isBridgeNetMode checks if the given network mode is bridge.
@@ -919,12 +923,8 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
var netStats *netlink.LinkStatistics
- // With slirp4netns, we can't collect statistics at present.
- // For now, we allow stats to at least run by returning nil
- if rootless.IsRootless() || ctr.config.NetMode.IsSlirp4netns() {
- return netStats, nil
- }
- netNSPath, netPathErr := getContainerNetNS(ctr)
+
+ netNSPath, otherCtr, netPathErr := getContainerNetNS(ctr)
if netPathErr != nil {
return nil, netPathErr
}
@@ -933,9 +933,18 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) {
// this is a valid state and thus return no error, nor any statistics
return nil, nil
}
+
+ // FIXME get the interface from the container netstatus
+ dev := "eth0"
+ netMode := ctr.config.NetMode
+ if otherCtr != nil {
+ netMode = otherCtr.config.NetMode
+ }
+ if netMode.IsSlirp4netns() {
+ dev = "tap0"
+ }
err := ns.WithNetNSPath(netNSPath, func(_ ns.NetNS) error {
- // FIXME get the interface from the container netstatus
- link, err := netlink.LinkByName("eth0")
+ link, err := netlink.LinkByName(dev)
if err != nil {
return err
}
@@ -1198,13 +1207,6 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe
// get network status before we connect
networkStatus := c.getNetworkStatus()
- network, err := c.runtime.network.NetworkInspect(netName)
- if err != nil {
- return err
- }
- if !network.DNSEnabled && len(netOpts.Aliases) > 0 {
- return errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
- }
// always add the short id as alias for docker compat
netOpts.Aliases = append(netOpts.Aliases, c.config.ID[:12])
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index 1c15d567c..1ee664e81 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -273,9 +273,11 @@ func readStdio(conn *net.UnixConn, streams *define.AttachStreams, receiveStdoutE
var err error
select {
case err = <-receiveStdoutError:
+ conn.CloseWrite()
return err
case err = <-stdinDone:
if err == define.ErrDetach {
+ conn.CloseWrite()
return err
}
if err == nil {
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 29c600109..04deaac83 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -389,6 +389,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
if err != nil {
return nil, nil, err
}
+ defer processFile.Close()
args := r.sharedConmonArgs(c, sessionID, c.execBundlePath(sessionID), c.execPidPath(sessionID), c.execLogPath(sessionID), c.execExitFileDir(sessionID), ociLog, define.NoLogging, "")
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 3fa43aed9..268a301fb 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -660,13 +660,13 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
}
errChan <- err
}()
+ if err := ctr.ReadLog(context.Background(), logOpts, logChan); err != nil {
+ return err
+ }
go func() {
logOpts.WaitGroup.Wait()
close(logChan)
}()
- if err := ctr.ReadLog(context.Background(), logOpts, logChan); err != nil {
- return err
- }
logrus.Debugf("Done reading logs for container %s, %d bytes", ctr.ID(), logSize)
if err := <-errChan; err != nil {
return err
diff --git a/libpod/reset.go b/libpod/reset.go
index 2b2b586bc..28d0ee3f6 100644
--- a/libpod/reset.go
+++ b/libpod/reset.go
@@ -7,6 +7,7 @@ import (
"path/filepath"
"github.com/containers/common/libimage"
+ "github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/errorhandling"
"github.com/containers/podman/v4/pkg/rootless"
@@ -70,6 +71,22 @@ func (r *Runtime) Reset(ctx context.Context) error {
}
}
+ // remove all networks
+ nets, err := r.network.NetworkList()
+ if err != nil {
+ return err
+ }
+ for _, net := range nets {
+ // do not delete the default network
+ if net.Name == r.network.DefaultNetworkName() {
+ continue
+ }
+ // ignore not exists errors because of the TOCTOU problem
+ if err := r.network.NetworkRemove(net.Name); err != nil && !errors.Is(err, types.ErrNoSuchNetwork) {
+ logrus.Errorf("Removing network %s: %v", net.Name, err)
+ }
+ }
+
xdgRuntimeDir := filepath.Clean(os.Getenv("XDG_RUNTIME_DIR"))
_, prevError := r.store.Shutdown(true)
graphRoot := filepath.Clean(r.store.GraphRoot())
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 6ee25c0ec..3799b463f 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -254,15 +254,6 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if err != nil {
return nil, err
}
- if len(opts.Aliases) > 0 {
- network, err := r.network.NetworkInspect(netName)
- if err != nil {
- return nil, err
- }
- if !network.DNSEnabled {
- return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
- }
- }
// assign interface name if empty
if opts.InterfaceName == "" {
for i < 100000 {
@@ -653,6 +644,20 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
}
}
+ // Check that no other containers depend on the container.
+ // Only used if not removing a pod - pods guarantee that all
+ // deps will be evicted at the same time.
+ if !removePod {
+ deps, err := r.state.ContainerInUse(c)
+ if err != nil {
+ return err
+ }
+ if len(deps) != 0 {
+ depsStr := strings.Join(deps, ", ")
+ return errors.Wrapf(define.ErrCtrExists, "container %s has dependent containers which must be removed before it: %s", c.ID(), depsStr)
+ }
+ }
+
// Check that the container's in a good state to be removed.
if c.state.State == define.ContainerStateRunning {
time := c.StopTimeout()
@@ -675,25 +680,6 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
}
}
- // Remove all active exec sessions
- if err := c.removeAllExecSessions(); err != nil {
- return err
- }
-
- // Check that no other containers depend on the container.
- // Only used if not removing a pod - pods guarantee that all
- // deps will be evicted at the same time.
- if !removePod {
- deps, err := r.state.ContainerInUse(c)
- if err != nil {
- return err
- }
- if len(deps) != 0 {
- depsStr := strings.Join(deps, ", ")
- return errors.Wrapf(define.ErrCtrExists, "container %s has dependent containers which must be removed before it: %s", c.ID(), depsStr)
- }
- }
-
var cleanupErr error
// Clean up network namespace, cgroups, mounts.
@@ -713,6 +699,14 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
return errors.Wrapf(err, "unable to set container %s removing state in database", c.ID())
}
+ // Remove all active exec sessions
+ // removing the exec sessions might temporarily unlock the container's lock. Using it
+ // after setting the state to ContainerStateRemoving will prevent that the container is
+ // restarted
+ if err := c.removeAllExecSessions(); err != nil {
+ return err
+ }
+
// Stop the container's storage
if err := c.teardownStorage(); err != nil {
if cleanupErr == nil {
diff --git a/libpod/util.go b/libpod/util.go
index 2b96a9449..307caa8c5 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -150,6 +150,10 @@ func queryPackageVersion(cmdArg ...string) string {
if outp, err := cmd.Output(); err == nil {
output = string(outp)
}
+ if cmdArg[0] == "/sbin/apk" {
+ prefix := cmdArg[len(cmdArg)-1] + " is owned by "
+ output = strings.Replace(output, prefix, "", 1)
+ }
}
return strings.Trim(output, "\n")
}
@@ -157,10 +161,11 @@ func queryPackageVersion(cmdArg ...string) string {
func packageVersion(program string) string { // program is full path
packagers := [][]string{
{"/usr/bin/rpm", "-q", "-f"},
- {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu
- {"/usr/bin/pacman", "-Qo"}, // Arch
- {"/usr/bin/qfile", "-qv"}, // Gentoo (quick)
- {"/usr/bin/equery", "b"}, // Gentoo (slow)
+ {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu
+ {"/usr/bin/pacman", "-Qo"}, // Arch
+ {"/usr/bin/qfile", "-qv"}, // Gentoo (quick)
+ {"/usr/bin/equery", "b"}, // Gentoo (slow)
+ {"/sbin/apk", "info", "-W"}, // Alpine
}
for _, cmd := range packagers {
diff --git a/pkg/api/handlers/compat/auth.go b/pkg/api/handlers/compat/auth.go
index 4c4ad8afd..7804c8230 100644
--- a/pkg/api/handlers/compat/auth.go
+++ b/pkg/api/handlers/compat/auth.go
@@ -28,7 +28,7 @@ func Auth(w http.ResponseWriter, r *http.Request) {
var authConfig docker.AuthConfig
err := json.NewDecoder(r.Body).Decode(&authConfig)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse request"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse request"))
return
}
diff --git a/pkg/api/handlers/compat/changes.go b/pkg/api/handlers/compat/changes.go
index f26f239dc..af0143fcf 100644
--- a/pkg/api/handlers/compat/changes.go
+++ b/pkg/api/handlers/compat/changes.go
@@ -20,7 +20,7 @@ func Changes(w http.ResponseWriter, r *http.Request) {
DiffType string `schema:"diffType"`
}{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
var diffType define.DiffType
@@ -32,7 +32,7 @@ func Changes(w http.ResponseWriter, r *http.Request) {
case "image":
diffType = define.DiffImage
default:
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Errorf("invalid diffType value %q", query.DiffType))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("invalid diffType value %q", query.DiffType))
return
}
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 94393886f..4830ef4b7 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -46,8 +46,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -61,8 +60,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
options.Depend = query.Depend
} else {
if query.Link {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- utils.ErrLinkNotSupport)
+ utils.Error(w, http.StatusBadRequest, utils.ErrLinkNotSupport)
return
}
options.Volumes = query.DockerVolumes
@@ -112,12 +110,12 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
return
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -189,7 +187,7 @@ func GetContainer(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -217,7 +215,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
Signal: "KILL",
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -232,7 +230,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
if err != nil {
if errors.Cause(err) == define.ErrCtrStateInvalid ||
errors.Cause(err) == define.ErrCtrStopped {
- utils.Error(w, fmt.Sprintf("Container %s is not running", name), http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
if errors.Cause(err) == define.ErrNoSuchCtr {
@@ -262,7 +260,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
Interval: time.Millisecond * 250,
}
if _, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
}
@@ -613,7 +611,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) {
Name string `schema:"name"`
}{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -625,7 +623,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) {
if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil {
if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists {
- utils.Error(w, "Something went wrong.", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
utils.InternalServerError(w, err)
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index a0e3c6d02..f2ff4d100 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -28,7 +28,7 @@ func Archive(w http.ResponseWriter, r *http.Request) {
case http.MethodHead, http.MethodGet:
handleHeadAndGet(w, r, decoder, runtime)
default:
- utils.Error(w, fmt.Sprintf("unsupported method: %v", r.Method), http.StatusNotImplemented, errors.New(fmt.Sprintf("unsupported method: %v", r.Method)))
+ utils.Error(w, http.StatusNotImplemented, errors.New(fmt.Sprintf("unsupported method: %v", r.Method)))
}
}
@@ -39,12 +39,12 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
err := decoder.Decode(&query, r.URL.Query())
if err != nil {
- utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
return
}
if query.Path == "" {
- utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.New("missing `path` parameter"))
+ utils.Error(w, http.StatusBadRequest, errors.New("missing `path` parameter"))
return
}
@@ -59,7 +59,7 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
if statReport != nil {
statHeader, err := copy.EncodeFileInfo(&statReport.FileInfo)
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
w.Header().Add(copy.XDockerContainerPathStatHeader, statHeader)
@@ -68,10 +68,10 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
if errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == copy.ErrENOENT {
// 404 is returned for an absent container and path. The
// clients must deal with it accordingly.
- utils.Error(w, "Not found.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
} else if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -83,7 +83,7 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
copyFunc, err := containerEngine.ContainerCopyToArchive(r.Context(), containerName, query.Path, w)
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
w.Header().Set("Content-Type", "application/x-tar")
@@ -106,14 +106,14 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
err := decoder.Decode(&query, r.URL.Query())
if err != nil {
- utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
return
}
var rename map[string]string
if query.Rename != "" {
if err := json.Unmarshal([]byte(query.Rename), &rename); err != nil {
- utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
return
}
}
@@ -126,16 +126,16 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) {
// 404 is returned for an absent container and path. The
// clients must deal with it accordingly.
- utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
+ utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
return
} else if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if err := copyFunc(); err != nil {
logrus.Error(err.Error())
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
w.WriteHeader(http.StatusOK)
diff --git a/pkg/api/handlers/compat/containers_attach.go b/pkg/api/handlers/compat/containers_attach.go
index ccdf054b9..027dadaa3 100644
--- a/pkg/api/handlers/compat/containers_attach.go
+++ b/pkg/api/handlers/compat/containers_attach.go
@@ -28,7 +28,7 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
Stream: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Error parsing parameters", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
@@ -60,13 +60,13 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
streams = nil
}
if useStreams && !streams.Stdout && !streams.Stderr && !streams.Stdin {
- utils.Error(w, "Parameter conflict", http.StatusBadRequest, errors.Errorf("at least one of stdin, stdout, stderr must be true"))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("at least one of stdin, stdout, stderr must be true"))
return
}
// At least one of these must be set
if !query.Stream && !query.Logs {
- utils.Error(w, "Unsupported parameter", http.StatusBadRequest, errors.Errorf("at least one of Logs or Stream must be set"))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("at least one of Logs or Stream must be set"))
return
}
@@ -85,7 +85,7 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
// For Docker compatibility, we need to re-initialize containers in these states.
if state == define.ContainerStateConfigured || state == define.ContainerStateExited {
if err := ctr.Init(r.Context(), ctr.PodID() != ""); err != nil {
- utils.Error(w, "Container in wrong state", http.StatusConflict, errors.Wrapf(err, "error preparing container %s for attach", ctr.ID()))
+ utils.Error(w, http.StatusConflict, errors.Wrapf(err, "error preparing container %s for attach", ctr.ID()))
return
}
} else if !(state == define.ContainerStateCreated || state == define.ContainerStateRunning) {
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 467231150..cd592a975 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -27,15 +27,14 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
// 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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
// compatible configuration
body := handlers.CreateContainerConfig{}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -43,18 +42,18 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
body.Name = query.Name
if len(body.HostConfig.Links) > 0 {
- utils.Error(w, utils.ErrLinkNotSupport.Error(), http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter"))
return
}
rtc, err := runtime.GetConfig()
if err != nil {
- utils.Error(w, "unable to obtain runtime config", http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config"))
return
}
imageName, err := utils.NormalizeToDockerHub(r, body.Config.Image)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
body.Config.Image = imageName
@@ -62,18 +61,18 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
newImage, resolvedName, err := runtime.LibimageRuntime().LookupImage(body.Config.Image, nil)
if err != nil {
if errors.Cause(err) == storage.ErrImageUnknown {
- utils.Error(w, "No such image", http.StatusNotFound, errors.Wrap(err, "No such image"))
+ utils.Error(w, http.StatusNotFound, errors.Wrap(err, "No such image"))
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error looking up image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error looking up image"))
return
}
// Take body structure and convert to cliopts
cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(body, rtc)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "make cli opts()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "make cli opts()"))
return
}
@@ -81,7 +80,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
// if the img had multi names with the same sha256 ID, should use the InputName, not the ID
if len(newImage.Names()) > 1 {
if err := utils.IsRegistryReference(resolvedName); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
// maybe the InputName has no tag, so use full name to display
@@ -90,7 +89,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
sg := specgen.NewSpecGenerator(imgNameOrID, cliOpts.RootFS)
if err := specgenutil.FillOutSpecGen(sg, cliOpts, args); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "fill out specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "fill out specgen"))
return
}
// moby always create the working directory
@@ -99,7 +98,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.ContainerCreate(r.Context(), sg)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "container create"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "container create"))
return
}
createResponse := entities.ContainerCreateResponse{
diff --git a/pkg/api/handlers/compat/containers_export.go b/pkg/api/handlers/compat/containers_export.go
index 8be1dcf99..743ce2d53 100644
--- a/pkg/api/handlers/compat/containers_export.go
+++ b/pkg/api/handlers/compat/containers_export.go
@@ -21,21 +21,21 @@ func ExportContainer(w http.ResponseWriter, r *http.Request) {
}
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
- utils.Error(w, "unable to create tarball tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "unable to close tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
return
}
if err := con.Export(tmpfile.Name()); err != nil {
- utils.Error(w, "failed to save the image", http.StatusInternalServerError, errors.Wrap(err, "failed to save image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to save image"))
return
}
rdr, err := os.Open(tmpfile.Name())
if err != nil {
- utils.Error(w, "failed to read temp tarball", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
return
}
defer rdr.Close()
diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go
index 20f71a4fe..fc894d815 100644
--- a/pkg/api/handlers/compat/containers_logs.go
+++ b/pkg/api/handlers/compat/containers_logs.go
@@ -36,13 +36,13 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
Tail: "all",
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if !(query.Stdout || query.Stderr) {
msg := fmt.Sprintf("%s: you must choose at least one stream", http.StatusText(http.StatusBadRequest))
- utils.Error(w, msg, http.StatusBadRequest, errors.Errorf("%s for %s", msg, r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("%s for %s", msg, r.URL.String()))
return
}
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go
index 2a2c9f678..9b5390d64 100644
--- a/pkg/api/handlers/compat/containers_prune.go
+++ b/pkg/api/handlers/compat/containers_prune.go
@@ -18,7 +18,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filtersMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/compat/containers_restart.go b/pkg/api/handlers/compat/containers_restart.go
index 66bca23e6..ded6480bc 100644
--- a/pkg/api/handlers/compat/containers_restart.go
+++ b/pkg/api/handlers/compat/containers_restart.go
@@ -29,8 +29,7 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) {
// 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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index c770a03f5..99f14d02f 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -29,11 +29,11 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
Stream: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if query.Stream && query.OneShot { // mismatch. one-shot can only be passed with stream=false
- utils.Error(w, "invalid combination of stream and one-shot", http.StatusBadRequest, define.ErrInvalidArg)
+ utils.Error(w, http.StatusBadRequest, define.ErrInvalidArg)
return
}
@@ -52,7 +52,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
return
}
if state != define.ContainerStateRunning {
- utils.Error(w, "Container not running and streaming requested", http.StatusConflict, define.ErrCtrStateInvalid)
+ utils.Error(w, http.StatusConflict, define.ErrCtrStateInvalid)
return
}
diff --git a/pkg/api/handlers/compat/containers_stop.go b/pkg/api/handlers/compat/containers_stop.go
index 5bc3a34ac..1c1fb310c 100644
--- a/pkg/api/handlers/compat/containers_stop.go
+++ b/pkg/api/handlers/compat/containers_stop.go
@@ -29,8 +29,7 @@ func StopContainer(w http.ResponseWriter, r *http.Request) {
// 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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go
index 6970cabe3..6ca178cf7 100644
--- a/pkg/api/handlers/compat/containers_top.go
+++ b/pkg/api/handlers/compat/containers_top.go
@@ -33,14 +33,12 @@ func TopContainer(w http.ResponseWriter, r *http.Request) {
PsArgs: psArgs,
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if query.Delay < 1 {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- fmt.Errorf("\"delay\" parameter of value %d < 1", query.Delay))
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("\"delay\" parameter of value %d < 1", query.Delay))
return
}
diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go
index cdee56aee..03b3d54bc 100644
--- a/pkg/api/handlers/compat/events.go
+++ b/pkg/api/handlers/compat/events.go
@@ -34,7 +34,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
Stream: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "failed to parse parameters", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -44,7 +44,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
libpodFilters, err := util.FiltersFromRequest(r)
if err != nil {
- utils.Error(w, "failed to parse parameters", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
eventChannel := make(chan *events.Event)
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
index c1ace5a38..c6f7e0318 100644
--- a/pkg/api/handlers/compat/exec.go
+++ b/pkg/api/handlers/compat/exec.go
@@ -2,7 +2,6 @@ package compat
import (
"encoding/json"
- "fmt"
"net/http"
"strings"
@@ -48,7 +47,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
for _, envStr := range input.Env {
split := strings.SplitN(envStr, "=", 2)
if len(split) != 2 {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr))
return
}
libpodConfig.Environment[split[0]] = split[1]
@@ -85,7 +84,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
// Ignore the error != nil case. We're already
// throwing an InternalServerError below.
if state == define.ContainerStatePaused {
- utils.Error(w, "Container is paused", http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID()))
+ utils.Error(w, http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID()))
return
}
}
@@ -107,7 +106,7 @@ func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
sessionID := mux.Vars(r)["id"]
sessionCtr, err := runtime.GetExecSessionContainer(sessionID)
if err != nil {
- utils.Error(w, fmt.Sprintf("No such exec session: %s", sessionID), http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -138,15 +137,14 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
bodyParams := new(handlers.ExecStartConfig)
if err := json.NewDecoder(r.Body).Decode(&bodyParams); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "failed to decode parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to decode parameters for %s", r.URL.String()))
return
}
// TODO: Verify TTY setting against what inspect session was made with
sessionCtr, err := runtime.GetExecSessionContainer(sessionID)
if err != nil {
- utils.Error(w, fmt.Sprintf("No such exec session: %s", sessionID), http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -158,7 +156,7 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) {
return
}
if state != define.ContainerStateRunning {
- utils.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict, errors.Errorf("cannot exec in a container that is not running; container %s is %s", sessionCtr.ID(), state.String()))
+ utils.Error(w, http.StatusConflict, errors.Errorf("cannot exec in a container that is not running; container %s is %s", sessionCtr.ID(), state.String()))
return
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 97fa4ddad..3546f88a0 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -50,7 +50,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
@@ -58,7 +58,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
@@ -74,18 +74,18 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
return
}
rdr, err := os.Open(tmpfile.Name())
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
return
}
defer rdr.Close()
@@ -97,25 +97,25 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
- Author string `schema:"author"`
- Changes string `schema:"changes"`
- Comment string `schema:"comment"`
- Container string `schema:"container"`
- Pause bool `schema:"pause"`
- Repo string `schema:"repo"`
- Tag string `schema:"tag"`
+ Author string `schema:"author"`
+ Changes []string `schema:"changes"`
+ Comment string `schema:"comment"`
+ Container string `schema:"container"`
+ Pause bool `schema:"pause"`
+ Repo string `schema:"repo"`
+ Tag string `schema:"tag"`
// fromSrc string # fromSrc is currently unused
}{
Tag: "latest",
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
rtc, err := runtime.GetConfig()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
sc := runtime.SystemContext()
@@ -131,17 +131,19 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
input := handlers.CreateContainerConfig{}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
options.Message = query.Comment
options.Author = query.Author
options.Pause = query.Pause
- options.Changes = strings.Fields(query.Changes)
+ for _, change := range query.Changes {
+ options.Changes = append(options.Changes, strings.Split(change, "\n")...)
+ }
ctr, err := runtime.LookupContainer(query.Container)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -150,7 +152,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
destImage = fmt.Sprintf("%s:%s", query.Repo, query.Tag)
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, destImage)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
destImage = possiblyNormalizedName
@@ -158,7 +160,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
commitImage, err := ctr.Commit(r.Context(), destImage, options)
if err != nil && !strings.Contains(err.Error(), "is not running") {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
return
}
utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: commitImage.ID()}) // nolint
@@ -182,7 +184,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
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.
@@ -190,13 +192,13 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
if source == "-" {
f, err := ioutil.TempFile("", "api_load.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
return
}
source = f.Name()
if err := SaveFromBody(f, r); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
}
}
@@ -204,7 +206,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
if query.Repo != "" {
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, reference)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
reference = possiblyNormalizedName
@@ -225,7 +227,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
report, err := imageEngine.Import(r.Context(), opts)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
return
}
// Success
@@ -261,19 +263,19 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
// This is where you can override the golang default value for one of fields
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, mergeNameAndTagOrDigest(query.FromImage, query.Tag))
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
authConf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -384,7 +386,7 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
@@ -393,12 +395,12 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
// Here we need to fiddle with the error message because docker-py is looking for "No
// such image" to determine on how to raise the correct exception.
errMsg := strings.ReplaceAll(err.Error(), "image not known", "No such image")
- utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Errorf("failed to find image %s: %s", name, errMsg))
+ utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find image %s: %s", name, errMsg))
return
}
inspect, err := handlers.ImageDataToImageInspect(r.Context(), newImage)
if err != nil {
- utils.Error(w, "Server error", http.StatusInternalServerError, errors.Wrapf(err, "failed to convert ImageData to ImageInspect '%s'", inspect.ID))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to convert ImageData to ImageInspect '%s'", inspect.ID))
return
}
utils.WriteResponse(w, http.StatusOK, inspect)
@@ -416,7 +418,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -427,7 +429,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
filterList, err := filters.FiltersFromRequest(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if !utils.IsLibpodRequest(r) {
@@ -442,7 +444,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
listOptions := entities.ImageListOptions{All: query.All, Filter: filterList}
summaries, err := imageEngine.List(r.Context(), listOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -470,7 +472,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -478,7 +480,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
// to load.
f, err := ioutil.TempFile("", "api_load.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile"))
return
}
defer func() {
@@ -488,7 +490,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
}
}()
if err := SaveFromBody(f, r); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file"))
return
}
@@ -497,19 +499,19 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
loadOptions := entities.ImageLoadOptions{Input: f.Name()}
loadReport, err := imageEngine.Load(r.Context(), loadOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to load image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to load image"))
return
}
- if len(loadReport.Names) != 1 {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Errorf("%d instead of 1 were loaded", len(loadReport.Names)))
+ if len(loadReport.Names) < 1 {
+ utils.Error(w, http.StatusInternalServerError, errors.Errorf("one or more images are required"))
return
}
utils.WriteResponse(w, http.StatusOK, struct {
Stream string `json:"stream"`
}{
- Stream: fmt.Sprintf("Loaded image: %s\n", loadReport.Names[0]),
+ Stream: fmt.Sprintf("Loaded image: %s", strings.Join(loadReport.Names, ",")),
})
}
@@ -525,11 +527,11 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
// This is where you can override the golang default value for one of fields
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if len(query.Names) <= 0 {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, fmt.Errorf("no images to download"))
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("no images to download"))
return
}
@@ -537,7 +539,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
for i, img := range query.Names {
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, img)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
images[i] = possiblyNormalizedName
@@ -545,12 +547,12 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
return
}
@@ -564,7 +566,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
rdr, err := os.Open(tmpfile.Name())
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
return
}
defer rdr.Close()
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index d9c9558e5..cc9667202 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -22,6 +22,7 @@ import (
api "github.com/containers/podman/v4/pkg/api/types"
"github.com/containers/podman/v4/pkg/auth"
"github.com/containers/podman/v4/pkg/channel"
+ "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/storage/pkg/archive"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/gorilla/schema"
@@ -133,7 +134,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
@@ -291,7 +292,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
if len(tags) > 0 {
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, tags[0])
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
output = possiblyNormalizedName
@@ -300,7 +301,17 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
registry := query.Registry
isolation := buildah.IsolationDefault
if utils.IsLibpodRequest(r) {
- isolation = parseLibPodIsolation(query.Isolation)
+ var err error
+ isolation, err = parseLibPodIsolation(query.Isolation)
+ if err != nil {
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to parse isolation"))
+ return
+ }
+
+ // make sure to force rootless as rootless otherwise buildah runs code which is intended to be run only as root.
+ if isolation == buildah.IsolationOCI && rootless.IsRootless() {
+ isolation = buildah.IsolationOCIRootless
+ }
registry = ""
format = query.OutputFormat
} else {
@@ -314,7 +325,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
for i := 1; i < len(tags); i++ {
possiblyNormalizedTag, err := utils.NormalizeToDockerHub(r, tags[i])
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
additionalTags = append(additionalTags, possiblyNormalizedTag)
@@ -457,7 +468,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
creds, authfile, err := auth.GetCredentials(r)
if err != nil {
// Credential value(s) not returned as their value is not human readable
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -466,7 +477,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
if fromImage != "" {
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, fromImage)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
fromImage = possiblyNormalizedName
@@ -698,22 +709,11 @@ func parseNetworkConfigurationPolicy(network string) buildah.NetworkConfiguratio
}
}
-func parseLibPodIsolation(isolation string) buildah.Isolation { // nolint
+func parseLibPodIsolation(isolation string) (buildah.Isolation, error) { // nolint
if val, err := strconv.Atoi(isolation); err == nil {
- return buildah.Isolation(val)
- }
- switch isolation {
- case "IsolationDefault", "default":
- return buildah.IsolationDefault
- case "IsolationOCI":
- return buildah.IsolationOCI
- case "IsolationChroot":
- return buildah.IsolationChroot
- case "IsolationOCIRootless":
- return buildah.IsolationOCIRootless
- default:
- return buildah.IsolationDefault
+ return buildah.Isolation(val), nil
}
+ return parse.IsolationOption(isolation)
}
func extractTarFile(r *http.Request) (string, error) {
diff --git a/pkg/api/handlers/compat/images_history.go b/pkg/api/handlers/compat/images_history.go
index dfaea0a76..70a11ddc5 100644
--- a/pkg/api/handlers/compat/images_history.go
+++ b/pkg/api/handlers/compat/images_history.go
@@ -16,7 +16,7 @@ func HistoryImage(w http.ResponseWriter, r *http.Request) {
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go
index 8fbf97248..88776dc49 100644
--- a/pkg/api/handlers/compat/images_prune.go
+++ b/pkg/api/handlers/compat/images_prune.go
@@ -24,7 +24,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index 6d4a8cdcf..6765c30b6 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -28,7 +28,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
digestFile, err := ioutil.TempFile("", "digest.txt")
if err != nil {
- utils.Error(w, "unable to create digest tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer digestFile.Close()
@@ -50,7 +50,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -63,14 +63,13 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
if _, err := utils.ParseStorageReference(imageName); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
return
}
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, imageName)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
imageName = possiblyNormalizedName
@@ -81,13 +80,13 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
rawManifest, _, err := localImage.Manifest(r.Context())
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
authconf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go
index df4644b2a..f45b38c66 100644
--- a/pkg/api/handlers/compat/images_remove.go
+++ b/pkg/api/handlers/compat/images_remove.go
@@ -25,7 +25,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if _, found := r.URL.Query()["noprune"]; found {
@@ -36,7 +36,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
@@ -53,7 +53,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
response := make([]map[string]string, 0, len(report.Untagged)+1)
diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go
index cdf7b12ab..9f41c1b4f 100644
--- a/pkg/api/handlers/compat/images_search.go
+++ b/pkg/api/handlers/compat/images_search.go
@@ -30,13 +30,13 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
_, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -58,7 +58,7 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
ir := abi.ImageEngine{Libpod: runtime}
reports, err := ir.Search(r.Context(), query.Term, options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if !utils.IsLibpodRequest(r) {
diff --git a/pkg/api/handlers/compat/images_tag.go b/pkg/api/handlers/compat/images_tag.go
index ce6b1de58..da0a04e84 100644
--- a/pkg/api/handlers/compat/images_tag.go
+++ b/pkg/api/handlers/compat/images_tag.go
@@ -17,7 +17,7 @@ func TagImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
@@ -34,7 +34,7 @@ func TagImage(w http.ResponseWriter, r *http.Request) {
tag = r.Form.Get("tag")
}
if len(r.Form.Get("repo")) < 1 {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
+ utils.Error(w, http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
return
}
repo := r.Form.Get("repo")
@@ -42,12 +42,12 @@ func TagImage(w http.ResponseWriter, r *http.Request) {
possiblyNormalizedTag, err := utils.NormalizeToDockerHub(r, tagName)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image"))
return
}
if err := newImage.Tag(possiblyNormalizedTag); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusCreated, "")
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index 42a513002..6286fdaee 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/sysinfo"
+ "github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/api/handlers"
@@ -32,18 +33,18 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
infoData, err := runtime.Info()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info"))
return
}
configInfo, err := runtime.GetConfig()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain runtime config"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain runtime config"))
return
}
versionInfo, err := define.GetVersion()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain podman versions"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain podman versions"))
return
}
stateInfo := getContainersState(runtime)
@@ -108,7 +109,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
Log: infoData.Plugins.Log,
},
ProductLicense: "Apache-2.0",
- RegistryConfig: new(registry.ServiceConfig),
+ RegistryConfig: getServiceConfig(runtime),
RuncCommit: docker.Commit{},
Runtimes: getRuntimes(configInfo),
SecurityOptions: getSecOpts(sysInfo),
@@ -133,6 +134,37 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, info)
}
+func getServiceConfig(runtime *libpod.Runtime) *registry.ServiceConfig {
+ var indexConfs map[string]*registry.IndexInfo
+
+ regs, err := sysregistriesv2.GetRegistries(runtime.SystemContext())
+ if err == nil {
+ indexConfs = make(map[string]*registry.IndexInfo, len(regs))
+ for _, reg := range regs {
+ mirrors := make([]string, len(reg.Mirrors))
+ for i, mirror := range reg.Mirrors {
+ mirrors[i] = mirror.Location
+ }
+ indexConfs[reg.Prefix] = &registry.IndexInfo{
+ Name: reg.Prefix,
+ Mirrors: mirrors,
+ Secure: !reg.Insecure,
+ }
+ }
+ } else {
+ log.Warnf("failed to get registries configuration: %v", err)
+ indexConfs = make(map[string]*registry.IndexInfo)
+ }
+
+ return &registry.ServiceConfig{
+ AllowNondistributableArtifactsCIDRs: make([]*registry.NetIPNet, 0),
+ AllowNondistributableArtifactsHostnames: make([]string, 0),
+ InsecureRegistryCIDRs: make([]*registry.NetIPNet, 0),
+ IndexConfigs: indexConfs,
+ Mirrors: make([]string, 0),
+ }
+}
+
func getGraphStatus(storeInfo map[string]string) [][2]string {
graphStatus := make([][2]string, 0, len(storeInfo))
for k, v := range storeInfo {
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 90a8b3c12..eb1a5d59c 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -36,12 +36,12 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
}
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if query.scope != "local" {
- utils.Error(w, "Invalid scope value. Can only be local.", http.StatusBadRequest, define.ErrInvalidArg)
+ utils.Error(w, http.StatusBadRequest, define.ErrInvalidArg)
return
}
name := utils.GetName(r)
@@ -133,7 +133,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -166,7 +166,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
if err := json.NewDecoder(r.Body).Decode(&networkCreate); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -262,7 +262,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -274,17 +274,17 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
reports, err := ic.NetworkRm(r.Context(), []string{name}, options)
if err != nil {
- utils.Error(w, "remove Network failed", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if len(reports) == 0 {
- utils.Error(w, "remove Network failed", http.StatusInternalServerError, errors.Errorf("internal error"))
+ utils.Error(w, http.StatusInternalServerError, errors.Errorf("internal error"))
return
}
report := reports[0]
if report.Err != nil {
if errors.Cause(report.Err) == define.ErrNoSuchNetwork {
- utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork)
+ utils.Error(w, http.StatusNotFound, define.ErrNoSuchNetwork)
return
}
utils.InternalServerError(w, report.Err)
@@ -302,7 +302,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
netConnect types.NetworkConnect
)
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -318,7 +318,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
if len(netConnect.EndpointConfig.IPAddress) > 0 {
staticIP := net.ParseIP(netConnect.EndpointConfig.IPAddress)
if staticIP == nil {
- utils.Error(w, "failed to parse the ip address", http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Errorf("failed to parse the ip address %q", netConnect.EndpointConfig.IPAddress))
return
}
@@ -330,7 +330,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
if len(netConnect.EndpointConfig.IPAMConfig.IPv4Address) > 0 {
staticIP := net.ParseIP(netConnect.EndpointConfig.IPAMConfig.IPv4Address)
if staticIP == nil {
- utils.Error(w, "failed to parse the ipv4 address", http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Errorf("failed to parse the ipv4 address %q", netConnect.EndpointConfig.IPAMConfig.IPv4Address))
return
}
@@ -340,7 +340,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
if len(netConnect.EndpointConfig.IPAMConfig.IPv6Address) > 0 {
staticIP := net.ParseIP(netConnect.EndpointConfig.IPAMConfig.IPv6Address)
if staticIP == nil {
- utils.Error(w, "failed to parse the ipv6 address", http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Errorf("failed to parse the ipv6 address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address))
return
}
@@ -351,7 +351,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
if len(netConnect.EndpointConfig.MacAddress) > 0 {
staticMac, err := net.ParseMAC(netConnect.EndpointConfig.MacAddress)
if err != nil {
- utils.Error(w, "failed to parse the mac address", http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Errorf("failed to parse the mac address %q", netConnect.EndpointConfig.IPAMConfig.IPv6Address))
return
}
@@ -365,10 +365,10 @@ func Connect(w http.ResponseWriter, r *http.Request) {
return
}
if errors.Cause(err) == define.ErrNoSuchNetwork {
- utils.Error(w, "network not found", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "OK")
@@ -380,7 +380,7 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
var netDisconnect types.NetworkDisconnect
if err := json.NewDecoder(r.Body).Decode(&netDisconnect); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -388,14 +388,14 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
err := runtime.DisconnectContainerFromNetwork(netDisconnect.Container, name, netDisconnect.Force)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
- utils.Error(w, "container not found", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
if errors.Cause(err) == define.ErrNoSuchNetwork {
- utils.Error(w, "network not found", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "OK")
@@ -406,7 +406,7 @@ func Prune(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -416,7 +416,7 @@ func Prune(w http.ResponseWriter, r *http.Request) {
}
pruneReports, err := ic.NetworkPrune(r.Context(), pruneOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
type response struct {
diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go
index 373d76f6b..ce7340f62 100644
--- a/pkg/api/handlers/compat/resize.go
+++ b/pkg/api/handlers/compat/resize.go
@@ -28,8 +28,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -51,7 +50,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
if errors.Cause(err) != define.ErrCtrStateInvalid {
utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container"))
} else {
- utils.Error(w, "Container not running", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
}
return
}
@@ -69,8 +68,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain session container state"))
return
} else if state != define.ContainerStateRunning && !query.IgnoreNotRunning {
- utils.Error(w, "Container not running", http.StatusConflict,
- fmt.Errorf("container %q in wrong state %q", name, state.String()))
+ utils.Error(w, http.StatusConflict, fmt.Errorf("container %q in wrong state %q", name, state.String()))
return
}
if err := ctnr.ExecResize(name, sz); err != nil {
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index b298ae626..0c2306dc8 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -4,7 +4,6 @@ import (
"bytes"
"encoding/base64"
"encoding/json"
- "fmt"
"net/http"
"github.com/containers/podman/v4/libpod"
@@ -22,8 +21,7 @@ func ListSecrets(w http.ResponseWriter, r *http.Request) {
)
filtersMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
- errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
ic := abi.ContainerEngine{Libpod: runtime}
@@ -116,12 +114,11 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
}{}
if err := json.NewDecoder(r.Body).Decode(&createParams); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
if len(createParams.Labels) > 0 {
- utils.Error(w, "labels not supported", http.StatusBadRequest,
- errors.Wrapf(errors.New("bad parameter"), "labels not supported"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(errors.New("bad parameter"), "labels not supported"))
return
}
@@ -133,7 +130,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
report, err := ic.SecretCreate(r.Context(), createParams.Name, reader, opts)
if err != nil {
if errors.Cause(err).Error() == "secret name in use" {
- utils.Error(w, "name conflicts with an existing object", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
utils.InternalServerError(w, err)
@@ -143,5 +140,5 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
}
func UpdateSecret(w http.ResponseWriter, r *http.Request) {
- utils.Error(w, fmt.Sprintf("unsupported endpoint: %v", r.Method), http.StatusNotImplemented, errors.New("update is not supported"))
+ utils.Error(w, http.StatusNotImplemented, errors.New("update is not supported"))
}
diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go
index c526a5aa2..b113fbc90 100644
--- a/pkg/api/handlers/compat/version.go
+++ b/pkg/api/handlers/compat/version.go
@@ -22,13 +22,13 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
running, err := define.GetVersion()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
info, err := runtime.Info()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info"))
return
}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index 352b5c7c3..c8e4339b0 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -26,7 +26,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
filtersMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -35,7 +35,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
// happily parse them for us.
for filter := range *filtersMap {
if filter == "opts" {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Errorf("unsupported libpod filters passed to docker endpoint"))
return
}
@@ -85,14 +85,14 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
/* No query string data*/
query := struct{}{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
// decode params from body
input := docker_api_types_volume.VolumeCreateBody{}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -220,7 +220,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -242,7 +242,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
// As above, we do not pass `force` from the query parameters here
if err := runtime.RemoveVolume(r.Context(), vol, false, query.Timeout); err != nil {
if errors.Cause(err) == define.ErrVolumeBeingUsed {
- utils.Error(w, "volumes being used", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
} else {
utils.InternalServerError(w, err)
}
@@ -268,14 +268,14 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
)
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
f := (url.Values)(*filterMap)
filterFuncs, err := filters.GeneratePruneVolumeFilters(f)
if err != nil {
- utils.Error(w, "Something when wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse filters for %s", f.Encode()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse filters for %s", f.Encode()))
return
}
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 2a0af6976..dfa09b8b8 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -35,8 +35,7 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -76,14 +75,12 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
- errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
return
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
- errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -134,8 +131,7 @@ func GetContainer(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
@@ -227,8 +223,7 @@ func Checkpoint(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -313,8 +308,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
// 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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -379,7 +373,7 @@ func InitContainer(w http.ResponseWriter, r *http.Request) {
}
err = ctr.Init(r.Context(), ctr.PodID() != "")
if errors.Cause(err) == define.ErrCtrStateInvalid {
- utils.Error(w, "container already initialized", http.StatusNotModified, err)
+ utils.Error(w, http.StatusNotModified, err)
return
}
if err != nil {
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index d579cc032..8e5fc1c1c 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -21,7 +21,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
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()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
if sg.Passwd == nil {
diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go
index d808bf1c0..d34254fd7 100644
--- a/pkg/api/handlers/libpod/containers_stats.go
+++ b/pkg/api/handlers/libpod/containers_stats.go
@@ -25,7 +25,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
// if so, then verify cgroup v2 available (more expensive check)
if isV2, _ := cgroups.IsCgroup2UnifiedMode(); !isV2 {
msg := "Container stats resource only available for cgroup v2"
- utils.Error(w, msg, http.StatusConflict, errors.New(msg))
+ utils.Error(w, http.StatusConflict, errors.New(msg))
return
}
}
@@ -39,7 +39,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
Interval: 5,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index aadb5ad52..7e08dd4a8 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -17,17 +17,20 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Name bool `schema:"useName"`
- New bool `schema:"new"`
- NoHeader bool `schema:"noHeader"`
- TemplateUnitFile bool `schema:"templateUnitFile"`
- RestartPolicy *string `schema:"restartPolicy"`
- RestartSec uint `schema:"restartSec"`
- StopTimeout uint `schema:"stopTimeout"`
- StartTimeout uint `schema:"startTimeout"`
- ContainerPrefix string `schema:"containerPrefix"`
- PodPrefix string `schema:"podPrefix"`
- Separator string `schema:"separator"`
+ Name bool `schema:"useName"`
+ New bool `schema:"new"`
+ NoHeader bool `schema:"noHeader"`
+ TemplateUnitFile bool `schema:"templateUnitFile"`
+ RestartPolicy *string `schema:"restartPolicy"`
+ RestartSec uint `schema:"restartSec"`
+ StopTimeout uint `schema:"stopTimeout"`
+ StartTimeout uint `schema:"startTimeout"`
+ ContainerPrefix string `schema:"containerPrefix"`
+ PodPrefix string `schema:"podPrefix"`
+ Separator string `schema:"separator"`
+ Wants []string `schema:"wants"`
+ After []string `schema:"after"`
+ Requires []string `schema:"requires"`
}{
StartTimeout: 0,
StopTimeout: util.DefaultContainerConfig().Engine.StopTimeout,
@@ -37,8 +40,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -55,11 +57,14 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
PodPrefix: query.PodPrefix,
Separator: query.Separator,
RestartSec: &query.RestartSec,
+ Wants: query.Wants,
+ After: query.After,
+ Requires: query.Requires,
}
report, err := containerEngine.GenerateSystemd(r.Context(), utils.GetName(r), options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error generating systemd units"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error generating systemd units"))
return
}
@@ -77,8 +82,7 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -86,7 +90,7 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) {
options := entities.GenerateKubeOptions{Service: query.Service}
report, err := containerEngine.GenerateKube(r.Context(), query.Names, options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error generating YAML"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error generating YAML"))
return
}
diff --git a/pkg/api/handlers/libpod/healthcheck.go b/pkg/api/handlers/libpod/healthcheck.go
index ba6e81bf1..bff092d21 100644
--- a/pkg/api/handlers/libpod/healthcheck.go
+++ b/pkg/api/handlers/libpod/healthcheck.go
@@ -19,11 +19,11 @@ func RunHealthCheck(w http.ResponseWriter, r *http.Request) {
return
}
if status == define.HealthCheckNotDefined {
- utils.Error(w, "no healthcheck defined", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
if status == define.HealthCheckContainerStopped {
- utils.Error(w, "container not running", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
utils.InternalServerError(w, err)
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index f9aade0ec..f078c13cc 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -48,11 +48,11 @@ func ImageExists(w http.ResponseWriter, r *http.Request) {
ir := abi.ImageEngine{Libpod: runtime}
report, err := ir.Exists(r.Context(), name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
return
}
if !report.Value {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Errorf("failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find image %s", name))
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
@@ -68,8 +68,7 @@ func ImageTree(w http.ResponseWriter, r *http.Request) {
WhatRequires: false,
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
ir := abi.ImageEngine{Libpod: runtime}
@@ -77,10 +76,10 @@ func ImageTree(w http.ResponseWriter, r *http.Request) {
report, err := ir.Tree(r.Context(), name, options)
if err != nil {
if errors.Cause(err) == storage.ErrImageUnknown {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
return
}
- utils.Error(w, "Server error", http.StatusInternalServerError, errors.Wrapf(err, "failed to generate image tree for %s", name))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to generate image tree for %s", name))
return
}
utils.WriteResponse(w, http.StatusOK, report)
@@ -90,13 +89,13 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
newImage, err := utils.GetImage(r, name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
return
}
options := &libimage.InspectOptions{WithParent: true, WithSize: true}
inspect, err := newImage.Inspect(r.Context(), options)
if err != nil {
- utils.Error(w, "Server error", http.StatusInternalServerError, errors.Wrapf(err, "failed in inspect image %s", inspect.ID))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed in inspect image %s", inspect.ID))
return
}
utils.WriteResponse(w, http.StatusOK, inspect)
@@ -117,14 +116,14 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.
Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
return
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.
Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
@@ -156,7 +155,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
}
imagePruneReports, err := imageEngine.Prune(r.Context(), pruneOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, imagePruneReports)
@@ -176,7 +175,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -191,23 +190,23 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
case define.OCIArchive, define.V2s2Archive:
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
- utils.Error(w, "unable to create tmpfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
output = tmpfile.Name()
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "unable to close tmpfile", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
return
}
case define.OCIManifestDir, define.V2s2ManifestDir:
tmpdir, err := ioutil.TempDir("", "save")
if err != nil {
- utils.Error(w, "unable to create tmpdir", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempdir"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempdir"))
return
}
output = tmpdir
default:
- utils.Error(w, "unknown format", http.StatusInternalServerError, errors.Errorf("unknown format %q", query.Format))
+ utils.Error(w, http.StatusInternalServerError, errors.Errorf("unknown format %q", query.Format))
return
}
@@ -219,7 +218,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
Output: output,
}
if err := imageEngine.Save(r.Context(), name, nil, saveOptions); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer os.RemoveAll(output)
@@ -236,7 +235,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
}
rdr, err := os.Open(output)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
return
}
defer rdr.Close()
@@ -259,22 +258,20 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
// References are mandatory!
if len(query.References) == 0 {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.New("No references"))
+ utils.Error(w, http.StatusBadRequest, errors.New("No references"))
return
}
// Format is mandatory! Currently, we only support multi-image docker
// archives.
if len(query.References) > 1 && query.Format != define.V2s2Archive {
- utils.Error(w, "unsupported format", http.StatusInternalServerError, errors.Errorf("multi-image archives must use format of %s", define.V2s2Archive))
+ utils.Error(w, http.StatusInternalServerError, errors.Errorf("multi-image archives must use format of %s", define.V2s2Archive))
return
}
@@ -292,23 +289,23 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
case define.V2s2Archive, define.OCIArchive:
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
- utils.Error(w, "unable to create tmpfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
output = tmpfile.Name()
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "unable to close tmpfile", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
return
}
case define.OCIManifestDir, define.V2s2ManifestDir:
tmpdir, err := ioutil.TempDir("", "save")
if err != nil {
- utils.Error(w, "unable to create tmpdir", http.StatusInternalServerError, errors.Wrap(err, "unable to create tmpdir"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tmpdir"))
return
}
output = tmpdir
default:
- utils.Error(w, "unsupported format", http.StatusInternalServerError, errors.Errorf("unsupported format %q", query.Format))
+ utils.Error(w, http.StatusInternalServerError, errors.Errorf("unsupported format %q", query.Format))
return
}
defer os.RemoveAll(output)
@@ -324,13 +321,13 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
if err := imageEngine.Save(r.Context(), query.References[0], query.References[1:], opts); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
rdr, err := os.Open(output)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
return
}
defer rdr.Close()
@@ -342,7 +339,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
@@ -351,7 +348,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
tmpfile.Close()
if err != nil && err != io.EOF {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
return
}
@@ -360,7 +357,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
loadOptions := entities.ImageLoadOptions{Input: tmpfile.Name()}
loadReport, err := imageEngine.Load(r.Context(), loadOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
return
}
utils.WriteResponse(w, http.StatusOK, loadReport)
@@ -379,8 +376,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -389,14 +385,14 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
if len(query.URL) == 0 {
tmpfile, err := ioutil.TempFile("", "libpod-images-import.tar")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer os.Remove(tmpfile.Name())
defer tmpfile.Close()
if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
return
}
@@ -413,7 +409,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
}
report, err := imageEngine.Import(r.Context(), importOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
return
}
@@ -434,13 +430,13 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
// This is where you can override the golang default value for one of fields
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
source := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
if _, err := utils.ParseStorageReference(source); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
@@ -450,13 +446,13 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
if err := utils.IsRegistryReference(destination); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
authconf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -479,7 +475,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
if err := imageEngine.Push(context.Background(), source, destination, options); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination))
return
}
@@ -508,12 +504,12 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
rtc, err := runtime.GetConfig()
if err != nil {
- utils.Error(w, "failed to get runtime config", http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config"))
return
}
sc := runtime.SystemContext()
@@ -550,7 +546,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
options.Changes = query.Changes
ctr, err := runtime.LookupContainer(query.Container)
if err != nil {
- utils.Error(w, "failed to lookup container", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -559,7 +555,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
}
commitImage, err := ctr.Commit(r.Context(), destImage, options)
if err != nil && !strings.Contains(err.Error(), "is not running") {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
return
}
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: commitImage.ID()}) // nolint
@@ -576,7 +572,7 @@ func UntagImage(w http.ResponseWriter, r *http.Request) {
switch {
// If tag is set, repo must be as well.
case len(repo) == 0 && len(tag) > 0:
- utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
+ utils.Error(w, http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
return
case len(repo) == 0:
@@ -601,7 +597,7 @@ func UntagImage(w http.ResponseWriter, r *http.Request) {
if errors.Cause(err) == storage.ErrImageUnknown {
utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
} else {
- utils.Error(w, "failed to untag", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
}
return
}
@@ -619,8 +615,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
}{}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -643,8 +638,7 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -662,12 +656,12 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
case 1:
// 404 - no such image
- utils.Error(w, "error removing image", http.StatusNotFound, errorhandling.JoinErrors(rmErrors))
+ utils.Error(w, http.StatusNotFound, errorhandling.JoinErrors(rmErrors))
case 2:
// 409 - conflict error (in use by containers)
- utils.Error(w, "error removing image", http.StatusConflict, errorhandling.JoinErrors(rmErrors))
+ utils.Error(w, http.StatusConflict, errorhandling.JoinErrors(rmErrors))
default:
// 500 - internal error
- utils.Error(w, "failed to remove image", http.StatusInternalServerError, errorhandling.JoinErrors(rmErrors))
+ utils.Error(w, http.StatusInternalServerError, errorhandling.JoinErrors(rmErrors))
}
}
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 945c5947a..2cd45fb63 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -41,8 +41,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -53,7 +52,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
// Make sure that the reference has no transport or the docker one.
if err := utils.IsRegistryReference(query.Reference); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
@@ -70,7 +69,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
// Do the auth dance.
authConf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -89,7 +88,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
pullPolicy, err := config.ParsePullPolicy(query.PullPolicy)
if err != nil {
- utils.Error(w, "failed to parse pull policy", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 69cf4fe7f..250736579 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -43,7 +43,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -52,7 +52,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) {
if name, ok := mux.Vars(r)["name"]; ok {
n, err := url.QueryUnescape(name)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse name parameter %q", name))
return
}
@@ -60,7 +60,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) {
}
if _, err := reference.ParseNormalizedNamed(query.Name); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "invalid image name %s", query.Name))
return
}
@@ -123,11 +123,11 @@ func ManifestExists(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
report, err := imageEngine.ManifestExists(r.Context(), name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if !report.Value {
- utils.Error(w, "manifest not found", http.StatusNotFound, errors.New("manifest not found"))
+ utils.Error(w, http.StatusNotFound, errors.New("manifest not found"))
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
@@ -140,13 +140,13 @@ func ManifestInspect(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
rawManifest, err := imageEngine.ManifestInspect(r.Context(), name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
var schema2List manifest.Schema2List
if err := json.Unmarshal(rawManifest, &schema2List); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -165,13 +165,13 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) {
Images []string
}{}
if err := json.NewDecoder(r.Body).Decode(&query); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
name := utils.GetName(r)
if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -197,18 +197,18 @@ func ManifestRemoveDigest(w http.ResponseWriter, r *http.Request) {
}
name := utils.GetName(r)
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
manifestList, err := runtime.LibimageRuntime().LookupManifestList(name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
d, err := digest.Parse(query.Digest)
if err != nil {
- utils.Error(w, "invalid digest", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
if err := manifestList.RemoveInstance(d); err != nil {
@@ -232,19 +232,19 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) {
// Add defaults here once needed.
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if err := utils.IsRegistryReference(query.Destination); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
source := utils.GetName(r)
authconf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -268,7 +268,7 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
digest, err := imageEngine.ManifestPush(context.Background(), source, query.Destination, options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", query.Destination))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", query.Destination))
return
}
utils.WriteResponse(w, http.StatusOK, digest)
@@ -288,20 +288,20 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
// Add defaults here once needed.
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
destination := utils.GetVar(r, "destination")
if err := utils.IsRegistryReference(destination); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
authconf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse registry header for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse registry header for %s", r.URL.String()))
return
}
defer auth.RemoveAuthfile(authfile)
@@ -327,7 +327,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
source := utils.GetName(r)
digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination))
return
}
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: digest})
@@ -340,13 +340,13 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) {
body := new(entities.ManifestModifyOptions)
if err := json.NewDecoder(r.Body).Decode(body); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
name := utils.GetName(r)
if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
@@ -392,8 +392,7 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) {
report.Images = append(report.Images, image)
}
default:
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- fmt.Errorf("illegal operation %q for %q", body.Operation, r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("illegal operation %q for %q", body.Operation, r.URL.String()))
return
}
@@ -414,7 +413,7 @@ func ManifestDelete(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
- utils.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index aebf601b7..71d46ce70 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -20,7 +20,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
network := types.Network{}
if err := json.NewDecoder(r.Body).Decode(&network); err != nil {
- utils.Error(w, "unable to marshall input", http.StatusInternalServerError, errors.Wrap(err, "decode body"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "decode body"))
return
}
@@ -36,7 +36,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -62,7 +62,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
// override any golang type defaults
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -80,7 +80,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
if reports[0].Err != nil {
// If the network cannot be found, we return a 404.
if errors.Cause(reports[0].Err) == define.ErrNoSuchNetwork {
- utils.Error(w, "Something went wrong", http.StatusNotFound, reports[0].Err)
+ utils.Error(w, http.StatusNotFound, reports[0].Err)
return
}
}
@@ -95,7 +95,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
// override any golang type defaults
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -105,7 +105,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
reports, errs, err := ic.NetworkInspect(r.Context(), []string{name}, options)
// If the network cannot be found, we return a 404.
if len(errs) > 0 {
- utils.Error(w, "Something went wrong", http.StatusNotFound, define.ErrNoSuchNetwork)
+ utils.Error(w, http.StatusNotFound, define.ErrNoSuchNetwork)
return
}
if err != nil {
@@ -121,7 +121,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
var netConnect entities.NetworkConnectOptions
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
name := utils.GetName(r)
@@ -132,10 +132,10 @@ func Connect(w http.ResponseWriter, r *http.Request) {
return
}
if errors.Cause(err) == define.ErrNoSuchNetwork {
- utils.Error(w, "network not found", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "OK")
@@ -149,11 +149,11 @@ func ExistsNetwork(w http.ResponseWriter, r *http.Request) {
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.NetworkExists(r.Context(), name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if !report.Value {
- utils.Error(w, "network not found", http.StatusNotFound, define.ErrNoSuchNetwork)
+ utils.Error(w, http.StatusNotFound, define.ErrNoSuchNetwork)
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
@@ -165,7 +165,7 @@ func Prune(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -175,7 +175,7 @@ func Prune(w http.ResponseWriter, r *http.Request) {
ic := abi.ContainerEngine{Libpod: runtime}
pruneReports, err := ic.NetworkPrune(r.Context(), pruneOptions)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if pruneReports == nil {
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index 0c480dfbf..515d0e5cf 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -37,8 +37,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -46,8 +45,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
for _, ipString := range query.StaticIPs {
ip := net.ParseIP(ipString)
if ip == nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Errorf("Invalid IP address %s", ipString))
+ utils.Error(w, http.StatusBadRequest, errors.Errorf("Invalid IP address %s", ipString))
return
}
staticIPs = append(staticIPs, ip)
@@ -57,8 +55,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
for _, macString := range query.StaticMACs {
mac, err := net.ParseMAC(macString)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
staticMACs = append(staticMACs, mac)
@@ -67,7 +64,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
// Fetch the K8s YAML file from the body, and copy it to a temp file.
tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer func() {
@@ -79,16 +76,16 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
if err := tmpfile.Close(); err != nil {
logrus.Warn(err)
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
return
}
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
return
}
authConf, authfile, err := auth.GetCredentials(r)
if err != nil {
- utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, err)
+ utils.Error(w, http.StatusBadRequest, err)
return
}
defer auth.RemoveAuthfile(authfile)
@@ -119,7 +116,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
}
report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file"))
return
}
utils.WriteResponse(w, http.StatusOK, report)
@@ -129,7 +126,7 @@ func PlayKubeDown(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml")
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
return
}
defer func() {
@@ -141,18 +138,18 @@ func PlayKubeDown(w http.ResponseWriter, r *http.Request) {
if err := tmpfile.Close(); err != nil {
logrus.Warn(err)
}
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
return
}
if err := tmpfile.Close(); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file"))
return
}
containerEngine := abi.ContainerEngine{Libpod: runtime}
options := new(entities.PlayKubeDownOptions)
report, err := containerEngine.PlayKubeDown(r.Context(), tmpfile.Name(), *options)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file"))
return
}
utils.WriteResponse(w, http.StatusOK, report)
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 5ebfdd034..d522631b7 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -24,17 +24,20 @@ import (
)
func PodCreate(w http.ResponseWriter, r *http.Request) {
+ const (
+ failedToDecodeSpecgen = "failed to decode specgen"
+ )
var (
runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
err error
)
psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}}
if err := json.NewDecoder(r.Body).Decode(&psg); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
return
}
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
return
}
if !psg.NoInfra {
@@ -48,17 +51,17 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, &infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen"))
return
}
out, err := json.Marshal(psg) // marshal our spec so the matching options can be unmarshaled into infra
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
return
}
err = json.Unmarshal(out, psg.InfraContainerSpec) // unmarhal matching options
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
return
}
// a few extra that do not have the same json tags
@@ -75,7 +78,7 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
if errors.Cause(err) == define.ErrPodExists {
httpCode = http.StatusConflict
}
- utils.Error(w, "Something went wrong.", httpCode, errors.Wrap(err, "failed to make pod"))
+ utils.Error(w, httpCode, errors.Wrap(err, "failed to make pod"))
return
}
utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()})
@@ -86,8 +89,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -97,7 +99,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
}
pods, err := containerEngine.PodPs(r.Context(), podPSOptions)
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, pods)
@@ -113,7 +115,7 @@ func PodInspect(w http.ResponseWriter, r *http.Request) {
}
podData, err := pod.Inspect()
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -137,8 +139,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
name := utils.GetName(r)
@@ -150,7 +151,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
status, err := pod.GetPodStatus()
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if status != define.PodStateRunning {
@@ -164,7 +165,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
responses, stopError = pod.Stop(r.Context(), false)
}
if stopError != nil && errors.Cause(stopError) != define.ErrPodPartialFail {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
// Try to clean up the pod - but only warn on failure, it's nonfatal.
@@ -197,7 +198,7 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
}
status, err := pod.GetPodStatus()
if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if status == define.PodStateRunning {
@@ -207,7 +208,7 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
responses, err := pod.Start(r.Context())
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
- utils.Error(w, "Something went wrong", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
@@ -236,8 +237,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
name := utils.GetName(r)
@@ -247,7 +247,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
return
}
if err := runtime.RemovePod(r.Context(), pod, true, query.Force, query.Timeout); err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
report := entities.PodRmReport{Id: pod.ID()}
@@ -264,7 +264,7 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
}
responses, err := pod.Restart(r.Context())
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -317,7 +317,7 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
}
responses, err := pod.Pause(r.Context())
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -343,7 +343,7 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) {
}
responses, err := pod.Unpause(r.Context())
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
- utils.Error(w, "failed to pause pod", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -376,14 +376,12 @@ func PodTop(w http.ResponseWriter, r *http.Request) {
PsArgs: psArgs,
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if query.Delay < 1 {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- fmt.Errorf("\"delay\" parameter of value %d < 1", query.Delay))
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("\"delay\" parameter of value %d < 1", query.Delay))
return
}
@@ -460,8 +458,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
// 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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
if _, found := r.URL.Query()["signal"]; found {
@@ -482,7 +479,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
logrus.Debugf("Killing pod %s with signal %d", pod.ID(), sig)
podStates, err := pod.Status()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
hasRunning := false
@@ -493,14 +490,13 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
}
}
if !hasRunning {
- msg := fmt.Sprintf("Container %s is not running", pod.ID())
- utils.Error(w, msg, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID()))
+ utils.Error(w, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID()))
return
}
responses, err := pod.Kill(r.Context(), uint(sig))
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
- utils.Error(w, "failed to kill pod", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -540,8 +536,7 @@ func PodStats(w http.ResponseWriter, r *http.Request) {
// default would go here
}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -558,7 +553,7 @@ func PodStats(w http.ResponseWriter, r *http.Request) {
// Error checks as documented in swagger.
switch errors.Cause(err) {
case define.ErrNoSuchPod:
- utils.Error(w, "one or more pods not found", http.StatusNotFound, err)
+ utils.Error(w, http.StatusNotFound, err)
return
case nil:
// Nothing to do.
diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go
index 2523dc139..8708e630c 100644
--- a/pkg/api/handlers/libpod/secrets.go
+++ b/pkg/api/handlers/libpod/secrets.go
@@ -35,8 +35,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
}
opts := entities.SecretCreateOptions{}
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()))
+ utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go
index f06d4b8c5..9ceca99e8 100644
--- a/pkg/api/handlers/libpod/system.go
+++ b/pkg/api/handlers/libpod/system.go
@@ -24,13 +24,13 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
}{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index 29085c06f..e0ea16d82 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -30,7 +30,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
// override any golang type defaults
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -38,7 +38,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
input := entities.VolumeCreateOptions{}
// 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()"))
+ utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -112,7 +112,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
)
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -187,7 +187,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
+ utils.Error(w, http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -199,7 +199,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
if err := runtime.RemoveVolume(r.Context(), vol, query.Force, query.Timeout); err != nil {
if errors.Cause(err) == define.ErrVolumeBeingUsed {
- utils.Error(w, "volumes being used", http.StatusConflict, err)
+ utils.Error(w, http.StatusConflict, err)
return
}
utils.InternalServerError(w, err)
@@ -216,11 +216,11 @@ func ExistsVolume(w http.ResponseWriter, r *http.Request) {
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.VolumeExists(r.Context(), name)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, http.StatusInternalServerError, err)
return
}
if !report.Value {
- utils.Error(w, "volume not found", http.StatusNotFound, define.ErrNoSuchVolume)
+ utils.Error(w, http.StatusNotFound, define.ErrNoSuchVolume)
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index d1e1164a4..3a5488a4a 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -39,7 +39,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) {
decoder := ctx.Value(api.DecoderKey).(*schema.Decoder)
if err = decoder.Decode(&query, r.URL.Query()); err != nil {
- Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -107,7 +107,7 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := waitQueryLibpod{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go
index 1bce19c10..bf60b2c84 100644
--- a/pkg/api/handlers/utils/errors.go
+++ b/pkg/api/handlers/utils/errors.go
@@ -1,7 +1,6 @@
package utils
import (
- "fmt"
"net/http"
"github.com/containers/podman/v4/libpod/define"
@@ -22,7 +21,7 @@ var (
//
// apiMessage and code must match the container API, and are sent to client
// err is logged on the system running the podman service
-func Error(w http.ResponseWriter, apiMessage string, code int, err error) {
+func Error(w http.ResponseWriter, code int, err error) {
// Log detailed message of what happened to machine running podman service
log.Infof("Request Failed(%s): %s", http.StatusText(code), err.Error())
em := errorhandling.ErrorModel{
@@ -37,70 +36,64 @@ func VolumeNotFound(w http.ResponseWriter, name string, err error) {
if errors.Cause(err) != define.ErrNoSuchVolume {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such volume: %s", name)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func ContainerNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != define.ErrNoSuchCtr {
+ switch errors.Cause(err) {
+ case define.ErrNoSuchCtr, define.ErrCtrExists:
+ Error(w, http.StatusNotFound, err)
+ default:
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such container: %s", name)
- Error(w, msg, http.StatusNotFound, err)
}
func ImageNotFound(w http.ResponseWriter, name string, err error) {
if errors.Cause(err) != storage.ErrImageUnknown {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such image: %s", name)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func NetworkNotFound(w http.ResponseWriter, name string, err error) {
if errors.Cause(err) != define.ErrNoSuchNetwork {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such network: %s", name)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func PodNotFound(w http.ResponseWriter, name string, err error) {
if errors.Cause(err) != define.ErrNoSuchPod {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such pod: %s", name)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func SessionNotFound(w http.ResponseWriter, name string, err error) {
if errors.Cause(err) != define.ErrNoSuchExecSession {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such exec session: %s", name)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func SecretNotFound(w http.ResponseWriter, nameOrID string, err error) {
if errors.Cause(err).Error() != "no such secret" {
InternalServerError(w, err)
}
- msg := fmt.Sprintf("No such secret: %s", nameOrID)
- Error(w, msg, http.StatusNotFound, err)
+ Error(w, http.StatusNotFound, err)
}
func ContainerNotRunning(w http.ResponseWriter, containerID string, err error) {
- msg := fmt.Sprintf("Container %s is not running", containerID)
- Error(w, msg, http.StatusConflict, err)
+ Error(w, http.StatusConflict, err)
}
func InternalServerError(w http.ResponseWriter, err error) {
- Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, err)
+ Error(w, http.StatusInternalServerError, err)
}
func BadRequest(w http.ResponseWriter, key string, value string, err error) {
e := errors.Wrapf(err, "failed to parse query parameter '%s': %q", key, value)
- Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, e)
+ Error(w, http.StatusBadRequest, e)
}
// UnsupportedParameter logs a given param by its string name as not supported.
diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go
index 47057959c..6b7f0cfe7 100644
--- a/pkg/api/server/register_generate.go
+++ b/pkg/api/server/register_generate.go
@@ -72,6 +72,27 @@ func (s *APIServer) registerGenerateHandlers(r *mux.Router) error {
// type: integer
// default: 0
// description: Configures the time to sleep before restarting a service.
+ // - in: query
+ // name: wants
+ // type: array
+ // items:
+ // type: string
+ // default: []
+ // description: Systemd Wants list for the container or pods.
+ // - in: query
+ // name: after
+ // type: array
+ // items:
+ // type: string
+ // default: []
+ // description: Systemd After list for the container or pods.
+ // - in: query
+ // name: requires
+ // type: array
+ // items:
+ // type: string
+ // default: []
+ // description: Systemd Requires list for the container or pods.
// produces:
// - application/json
// responses:
diff --git a/pkg/api/server/register_swarm.go b/pkg/api/server/register_swarm.go
index 9bb1b1c7c..6b0bad4ac 100644
--- a/pkg/api/server/register_swarm.go
+++ b/pkg/api/server/register_swarm.go
@@ -31,5 +31,5 @@ func (s *APIServer) registerSwarmHandlers(r *mux.Router) error {
// this allows the client to decide if they still can talk to us
func noSwarm(w http.ResponseWriter, r *http.Request) {
logrus.Errorf("%s is not a podman supported service", r.URL.String())
- utils.Error(w, "node is not part of a swarm", http.StatusServiceUnavailable, errors.New("Podman does not support service: "+r.URL.String()))
+ utils.Error(w, http.StatusServiceUnavailable, errors.New("Podman does not support service: "+r.URL.String()))
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 7b0e7a5a7..9b652be87 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -1,7 +1,6 @@
package server
import (
- "github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/entities/reports"
@@ -189,7 +188,7 @@ type swagVolumeCreateResponse struct {
// swagger:response VolumeList
type swagVolumeListResponse struct {
// in:body
- Body []libpod.Volume
+ Body []entities.VolumeConfigResponse
}
// Healthcheck
diff --git a/pkg/auth/auth_test.go b/pkg/auth/auth_test.go
index 2c79f0b7c..f25cbf2cc 100644
--- a/pkg/auth/auth_test.go
+++ b/pkg/auth/auth_test.go
@@ -31,7 +31,7 @@ var largeAuthFileValues = map[string]types.DockerAuthConfig{
// systemContextForAuthFile returns a types.SystemContext with AuthFilePath pointing
// to a temporary file with fileContents, or nil if fileContents is empty; and a cleanup
-// function the calle rmust arrange to call.
+// function the caller must arrange to call.
func systemContextForAuthFile(t *testing.T, fileContents string) (*types.SystemContext, func()) {
if fileContents == "" {
return nil, func() {}
diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go
index ce560c547..25c398c8b 100644
--- a/pkg/bindings/generate/types.go
+++ b/pkg/bindings/generate/types.go
@@ -32,4 +32,10 @@ type SystemdOptions struct {
PodPrefix *string
// Separator - systemd unit name separator between name/id and prefix
Separator *string
+ // Wants - systemd wants list for the container or pods
+ Wants *[]string
+ // After - systemd after list for the container or pods
+ After *[]string
+ // Requires - systemd requires list for the container or pods
+ Requires *[]string
}
diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go
index 960e45e50..4d436945b 100644
--- a/pkg/bindings/generate/types_systemd_options.go
+++ b/pkg/bindings/generate/types_systemd_options.go
@@ -181,3 +181,48 @@ func (o *SystemdOptions) GetSeparator() string {
}
return *o.Separator
}
+
+// WithWants set field Wants to given value
+func (o *SystemdOptions) WithWants(value []string) *SystemdOptions {
+ o.Wants = &value
+ return o
+}
+
+// GetWants returns value of field Wants
+func (o *SystemdOptions) GetWants() []string {
+ if o.Wants == nil {
+ var z []string
+ return z
+ }
+ return *o.Wants
+}
+
+// WithAfter set field After to given value
+func (o *SystemdOptions) WithAfter(value []string) *SystemdOptions {
+ o.After = &value
+ return o
+}
+
+// GetAfter returns value of field After
+func (o *SystemdOptions) GetAfter() []string {
+ if o.After == nil {
+ var z []string
+ return z
+ }
+ return *o.After
+}
+
+// WithRequires set field Requires to given value
+func (o *SystemdOptions) WithRequires(value []string) *SystemdOptions {
+ o.Requires = &value
+ return o
+}
+
+// GetRequires returns value of field Requires
+func (o *SystemdOptions) GetRequires() []string {
+ if o.Requires == nil {
+ var z []string
+ return z
+ }
+ return *o.Requires
+}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index b7220f5c5..a363f2c6e 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -332,7 +332,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
tarContent := []string{options.ContextDirectory}
- newContainerFiles := []string{}
+ newContainerFiles := []string{} // dockerfile paths, relative to context dir, ToSlash()ed
dontexcludes := []string{"!Dockerfile", "!Containerfile", "!.dockerignore", "!.containerignore"}
for _, c := range containerFiles {
@@ -380,7 +380,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
tarContent = append(tarContent, containerfile)
}
}
- newContainerFiles = append(newContainerFiles, containerfile)
+ newContainerFiles = append(newContainerFiles, filepath.ToSlash(containerfile))
}
if len(newContainerFiles) > 0 {
cFileJSON, err := json.Marshal(newContainerFiles)
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index d1a07598e..f51e5f404 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -86,7 +86,7 @@ func (b *bindingTest) runPodman(command []string) *gexec.Session {
}
val, ok = os.LookupEnv("CNI_CONFIG_DIR")
if ok {
- cmd = append(cmd, "--cni-config-dir", val)
+ cmd = append(cmd, "--network-config-dir", val)
}
val, ok = os.LookupEnv("CONMON")
if ok {
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index af2bad691..9411d8a5f 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -714,7 +714,7 @@ var _ = Describe("Podman containers ", func() {
var name = "top"
cid, err := bt.RunTopContainer(&name, nil)
Expect(err).To(BeNil())
- // Forcably Removing running container should succeed
+ // Forcibly Removing running container should succeed
rmResponse, err := containers.Remove(bt.conn, cid, new(containers.RemoveOptions).WithForce(true))
Expect(err).To(BeNil())
Expect(len(reports.RmReportsErrs(rmResponse))).To(Equal(0))
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
index e431a70af..73dd64ecd 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -26,6 +26,12 @@ type GenerateSystemdOptions struct {
NoHeader bool
// TemplateUnitFile - make use of %i and %I to differentiate between the different instances of the unit
TemplateUnitFile bool
+ // Wants - systemd wants list for the container or pods
+ Wants []string
+ // After - systemd after list for the container or pods
+ After []string
+ // Requires - systemd requires list for the container or pods
+ Requires []string
}
// GenerateSystemdReport
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index 79edc3227..a057640b3 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -43,12 +43,12 @@ type NetworkRmReport struct {
type NetworkCreateOptions struct {
DisableDNS bool
Driver string
- Gateway net.IP
+ Gateways []net.IP
Internal bool
Labels map[string]string
MacVLAN string
- Range net.IPNet
- Subnet net.IPNet
+ Ranges []string
+ Subnets []string
IPv6 bool
// Mapping of driver options and values.
Options map[string]string
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 3adf9b26c..0b1281aac 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -12,6 +12,7 @@ import (
"path/filepath"
"strconv"
"strings"
+ "syscall"
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
@@ -94,7 +95,9 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption
func toDomainHistoryLayer(layer *libimage.ImageHistory) entities.ImageHistoryLayer {
l := entities.ImageHistoryLayer{}
l.ID = layer.ID
- l.Created = *layer.Created
+ if layer.Created != nil {
+ l.Created = *layer.Created
+ }
l.CreatedBy = layer.CreatedBy
copy(l.Tags, layer.Tags)
l.Size = layer.Size
@@ -780,7 +783,7 @@ func transferRootless(source entities.ImageScpOptions, dest entities.ImageScpOpt
return cmdLoad.Run()
}
-// TransferRootful creates new podman processes using exec.Command and su/machinectl, transferring images between the given source and destination users
+// TransferRootful creates new podman processes using exec.Command and a new uid/gid alongside a cleared environment
func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOptions, podman string, parentFlags []string) error {
basicCommand := []string{podman}
basicCommand = append(basicCommand, parentFlags...)
@@ -792,12 +795,9 @@ func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOpti
}
saveCommand = append(saveCommand, []string{"--output", source.File, source.Image}...)
loadCommand = append(loadCommand, []string{"--input", dest.File}...)
- save := []string{strings.Join(saveCommand, " ")}
- load := []string{strings.Join(loadCommand, " ")}
- // if executing using sudo or transferring between two users, the TransferRootless approach will not work, default to using machinectl or su as necessary.
- // the approach using sudo is preferable and more straightforward. There is no reason for using sudo in these situations
- // since the feature is meant to transfer from root to rootless an vice versa without explicit sudo evocaiton.
+ // if executing using sudo or transferring between two users, the TransferRootless approach will not work, the new process needs to be set up
+ // with the proper uid and gid as well as environmental variables.
var uSave *user.User
var uLoad *user.User
var err error
@@ -828,20 +828,11 @@ func transferRootful(source entities.ImageScpOptions, dest entities.ImageScpOpti
return err
}
}
- machinectl, err := exec.LookPath("machinectl")
- if err != nil {
- logrus.Warn("defaulting to su since machinectl is not available, su will fail if no user session is available")
- err = execSu(uSave, save)
- if err != nil {
- return err
- }
- return execSu(uLoad, load)
- }
- err = execMachine(uSave, saveCommand, machinectl)
+ err = execPodman(uSave, saveCommand)
if err != nil {
return err
}
- return execMachine(uLoad, loadCommand, machinectl)
+ return execPodman(uLoad, loadCommand)
}
func lookupUser(u string) (*user.User, error) {
@@ -851,21 +842,37 @@ func lookupUser(u string) (*user.User, error) {
return user.Lookup(u)
}
-func execSu(execUser *user.User, command []string) error {
- cmd := exec.Command("su", "-l", execUser.Username, "--command")
- cmd = utils.CreateSCPCommand(cmd, command)
- logrus.Debugf("Executing via su: %q", cmd)
- return cmd.Run()
-}
-
-func execMachine(execUser *user.User, command []string, machinectl string) error {
- verb := machinectl
- args := []string{"shell", "-q", execUser.Username + "@.host"}
- if execUser.Uid == "0" {
- args = append([]string{verb}, args...)
- verb = "sudo"
+func execPodman(execUser *user.User, command []string) error {
+ cmdLogin, err := utils.LoginUser(execUser.Username)
+ if err != nil {
+ return err
+ }
+ defer func() error {
+ err := cmdLogin.Process.Kill()
+ if err != nil {
+ return err
+ }
+ return cmdLogin.Wait()
+ }()
+ cmd := exec.Command(command[0], command[1:]...)
+ cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "TERM=" + os.Getenv("TERM")}
+ cmd.Stderr = os.Stderr
+ cmd.Stdout = os.Stdout
+ uid, err := strconv.ParseInt(execUser.Uid, 10, 32)
+ if err != nil {
+ return err
+ }
+ gid, err := strconv.ParseInt(execUser.Gid, 10, 32)
+ if err != nil {
+ return err
+ }
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Credential: &syscall.Credential{
+ Uid: uint32(uid),
+ Gid: uint32(gid),
+ Groups: nil,
+ NoSetGroups: false,
+ },
}
- cmd := utils.CreateSCPCommand(exec.Command(verb, args...), command)
- logrus.Debugf("Executing via machinectl: %q", cmd)
return cmd.Run()
}
diff --git a/pkg/domain/infra/abi/images_test.go b/pkg/domain/infra/abi/images_test.go
index 20ef1b150..e38b9390d 100644
--- a/pkg/domain/infra/abi/images_test.go
+++ b/pkg/domain/infra/abi/images_test.go
@@ -1,5 +1,22 @@
package abi
+import (
+ "testing"
+
+ "github.com/containers/common/libimage"
+ "github.com/stretchr/testify/assert"
+)
+
+// This is really intended to verify what happens with a
+// nil pointer in layer.Created, but we'll just sanity
+// check round tripping 42.
+func TestToDomainHistoryLayer(t *testing.T) {
+ var layer libimage.ImageHistory
+ layer.Size = 42
+ newLayer := toDomainHistoryLayer(&layer)
+ assert.Equal(t, layer.Size, newLayer.Size)
+}
+
//
// import (
// "context"
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 86a60e92d..cad8c4609 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -365,6 +365,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
+
+ for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
+ labels[k] = v
+ }
+
specgenOpts := kube.CtrSpecGenOptions{
Annotations: annotations,
Container: initCtr,
@@ -405,7 +410,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
+ for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
+ labels[k] = v
+ }
+
specgenOpts := kube.CtrSpecGenOptions{
+ Annotations: annotations,
Container: container,
Image: pulledImage,
Volumes: volumes,
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index 519af5ab7..f9ceb9305 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -223,7 +223,7 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO flag to set libpod static dir?
// TODO flag to set libpod tmp dir?
- if fs.Changed("cni-config-dir") {
+ if fs.Changed("network-config-dir") {
options = append(options, libpod.WithCNIConfigDir(cfg.Network.NetworkConfigDir))
}
if fs.Changed("default-mounts-file") {
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index 49b66e908..235d478ec 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -8,7 +8,17 @@ import (
)
func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, opts entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
- options := new(generate.SystemdOptions).WithUseName(opts.Name).WithContainerPrefix(opts.ContainerPrefix).WithNew(opts.New).WithNoHeader(opts.NoHeader).WithTemplateUnitFile(opts.TemplateUnitFile).WithPodPrefix(opts.PodPrefix).WithSeparator(opts.Separator)
+ options := new(
+ generate.SystemdOptions).
+ WithUseName(opts.Name).
+ WithContainerPrefix(opts.ContainerPrefix).
+ WithNew(opts.New).WithNoHeader(opts.NoHeader).
+ WithTemplateUnitFile(opts.TemplateUnitFile).
+ WithPodPrefix(opts.PodPrefix).
+ WithSeparator(opts.Separator).
+ WithWants(opts.Wants).
+ WithAfter(opts.After).
+ WithRequires(opts.Requires)
if opts.StartTimeout != nil {
options.WithStartTimeout(*opts.StartTimeout)
diff --git a/pkg/env/env_supported.go b/pkg/env/env_unix.go
index 8be9f9592..16061a700 100644
--- a/pkg/env/env_supported.go
+++ b/pkg/env/env_unix.go
@@ -1,4 +1,4 @@
-// +build linux darwin
+// +build !windows
package env
diff --git a/pkg/env/env_unsupported.go b/pkg/env/env_unsupported.go
deleted file mode 100644
index a71c2956d..000000000
--- a/pkg/env/env_unsupported.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !linux,!darwin
-
-package env
-
-func ParseSlice(s []string) (map[string]string, error) {
- m := make(map[string]string)
- return m, nil
-}
diff --git a/pkg/env/env_windows.go b/pkg/env/env_windows.go
new file mode 100644
index 000000000..5df08fadc
--- /dev/null
+++ b/pkg/env/env_windows.go
@@ -0,0 +1,25 @@
+package env
+
+// ParseSlice parses the specified slice and transforms it into an environment
+// map.
+func ParseSlice(s []string) (map[string]string, error) {
+ env := make(map[string]string, len(s))
+ for _, e := range s {
+ if len(e) > 0 && e[0] == '=' {
+ // The legacy Windows CMD command interpreter uses a hack, where to emulate
+ // DOS semantics, it uses an illegal (by windows definition) env name for
+ // state storage to avoid conlficting with user defined env names. This is
+ // used to preserve drive letter paths. E.g., typing c: from another drive
+ // will remember the last CWD because CMD stores it in an env named "=C:".
+ // Since these are illegal, they are filtered from standard user access but
+ // are still available in the underlying win32 API calls. Since they have
+ // zero value to a container, we filter as well.
+ continue
+ }
+
+ if err := parseEnv(env, e); err != nil {
+ return nil, err
+ }
+ }
+ return env, nil
+}
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 09228553c..206c9144f 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -243,12 +243,15 @@ ExecStart=/usr/bin/sleep infinity
`
containers := `[containers]
netns="bridge"
-rootless_networking="cni"
`
rootContainers := `[engine]
machine_enabled=true
`
+ delegateConf := `[Service]
+Delegate=memory pids cpu io
+`
+
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
Node: Node{
@@ -281,6 +284,24 @@ machine_enabled=true
Mode: intToPtr(0744),
},
})
+
+ // Set delegate.conf so cpu,io subsystem is delegated to non-root users as well for cgroupv2
+ // by default
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/etc/systemd/system/user@.service.d/delegate.conf",
+ User: getNodeUsr("root"),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: encodeDataURLPtr(delegateConf),
+ },
+ Mode: intToPtr(0644),
+ },
+ })
+
// Add a file into linger
files = append(files, File{
Node: Node{
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index e1870f1ac..eb7b35ece 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -390,12 +390,14 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
if err != nil {
return err
}
- for running || !v.isListening() {
+ listening := v.isListening()
+ for !running || !listening {
time.Sleep(100 * time.Millisecond)
running, err = v.isRunning()
if err != nil {
return err
}
+ listening = v.isListening()
}
}
for _, mount := range v.Mounts {
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 6cab855d3..3edf3ddf6 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -1,4 +1,3 @@
-//go:build windows
// +build windows
package wsl
@@ -143,6 +142,11 @@ http://docs.microsoft.com/en-us/windows/wsl/install\
`
+const (
+ winSShProxy = "win-sshproxy.exe"
+ winSshProxyTid = "win-sshproxy.tid"
+)
+
type Provider struct{}
type MachineVM struct {
@@ -563,7 +567,7 @@ func installWslKernel() error {
}
// In case of unusual circumstances (e.g. race with installer actions)
// retry a few times
- message = "An error occured attempting the WSL Kernel update, retrying..."
+ message = "An error occurred attempting the WSL Kernel update, retrying..."
fmt.Println(message)
fmt.Fprintln(log, message)
time.Sleep(backoff)
@@ -705,8 +709,6 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
return errors.Errorf("%q is already running", name)
}
- fmt.Println("Starting machine...")
-
dist := toDist(name)
err := runCmdPassThrough("wsl", "-d", dist, "/root/bootstrap")
@@ -714,9 +716,107 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
return errors.Wrap(err, "WSL bootstrap script failed")
}
+ globalName, pipeName, err := launchWinProxy(v)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
+ fmt.Fprintf(os.Stderr, "\t%s\n", err.Error())
+ fmt.Fprintln(os.Stderr, "\nPodman clients are still able to connect.")
+ } else {
+ fmt.Printf("API forwarding listening on: %s\n", pipeName)
+ if globalName {
+ fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n")
+ } else {
+ fmt.Printf("\nAnother process was listening on the default Docker API pipe address.\n")
+ fmt.Printf("You can still connect Docker API clients by setting DOCKER HOST using the\n")
+ fmt.Printf("following powershell command in your terminal session:\n")
+ fmt.Printf("\n\t$Env:DOCKER_HOST = '%s'\n", pipeName)
+ fmt.Printf("\nOr in a classic CMD prompt:\n")
+ fmt.Printf("\n\tset DOCKER_HOST = '%s'\n", pipeName)
+ fmt.Printf("\nAlternatively terminate the other process and restart podman machine.\n")
+ }
+ }
+
return markStart(name)
}
+func launchWinProxy(v *MachineVM) (bool, string, error) {
+ globalName := true
+ pipeName := "docker_engine"
+ if !pipeAvailable(pipeName) {
+ pipeName = toDist(v.Name)
+ globalName = false
+ if !pipeAvailable(pipeName) {
+ return globalName, "", errors.Errorf("could not start api proxy since expected pipe is not available: %s", pipeName)
+ }
+ }
+ fullPipeName := "npipe:////./pipe/" + pipeName
+
+ exe, err := os.Executable()
+ if err != nil {
+ return globalName, "", err
+ }
+
+ exe, err = filepath.EvalSymlinks(exe)
+ if err != nil {
+ return globalName, "", err
+ }
+
+ command := filepath.Join(filepath.Dir(exe), winSShProxy)
+ stateDir, err := getWinProxyStateDir(v)
+ if err != nil {
+ return globalName, "", err
+ }
+
+ dest := fmt.Sprintf("ssh://root@localhost:%d/run/podman/podman.sock", v.Port)
+ cmd := exec.Command(command, v.Name, stateDir, fullPipeName, dest, v.IdentityPath)
+ if err := cmd.Start(); err != nil {
+ return globalName, "", err
+ }
+
+ return globalName, fullPipeName, waitPipeExists(pipeName, 30, func() error {
+ active, exitCode := getProcessState(cmd.Process.Pid)
+ if !active {
+ return errors.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode)
+ }
+
+ return nil
+ })
+}
+
+func getWinProxyStateDir(v *MachineVM) (string, error) {
+ dir, err := machine.GetDataDir(vmtype)
+ if err != nil {
+ return "", err
+ }
+ stateDir := filepath.Join(dir, v.Name)
+ if err = os.MkdirAll(stateDir, 0755); err != nil {
+ return "", err
+ }
+
+ return stateDir, nil
+}
+
+func pipeAvailable(pipeName string) bool {
+ _, err := os.Stat(`\\.\pipe\` + pipeName)
+ return os.IsNotExist(err)
+}
+
+func waitPipeExists(pipeName string, retries int, checkFailure func() error) error {
+ var err error
+ for i := 0; i < retries; i++ {
+ _, err = os.Stat(`\\.\pipe\` + pipeName)
+ if err == nil {
+ break
+ }
+ if fail := checkFailure(); fail != nil {
+ return fail
+ }
+ time.Sleep(100 * time.Millisecond)
+ }
+
+ return err
+}
+
func isWSLInstalled() bool {
cmd := exec.Command("wsl", "--status")
out, err := cmd.StdoutPipe()
@@ -817,6 +917,10 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
return errors.Errorf("%q is not running", v.Name)
}
+ if err := stopWinProxy(v); err != nil {
+ fmt.Fprintf(os.Stderr, "Could not stop API forwarding service (win-sshproxy.exe): %s\n", err.Error())
+ }
+
cmd := exec.Command("wsl", "-d", dist, "sh")
cmd.Stdin = strings.NewReader(waitTerm)
if err = cmd.Start(); err != nil {
@@ -840,6 +944,59 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
return nil
}
+func stopWinProxy(v *MachineVM) error {
+ pid, tid, tidFile, err := readWinProxyTid(v)
+ if err != nil {
+ return err
+ }
+
+ proc, err := os.FindProcess(int(pid))
+ if err != nil {
+ return nil
+ }
+ sendQuit(tid)
+ _ = waitTimeout(proc, 20*time.Second)
+ _ = os.Remove(tidFile)
+
+ return nil
+}
+
+func waitTimeout(proc *os.Process, timeout time.Duration) bool {
+ done := make(chan bool)
+ go func() {
+ proc.Wait()
+ done <- true
+ }()
+ ret := false
+ select {
+ case <-time.After(timeout):
+ proc.Kill()
+ <-done
+ case <-done:
+ ret = true
+ break
+ }
+
+ return ret
+}
+
+func readWinProxyTid(v *MachineVM) (uint32, uint32, string, error) {
+ stateDir, err := getWinProxyStateDir(v)
+ if err != nil {
+ return 0, 0, "", err
+ }
+
+ tidFile := filepath.Join(stateDir, winSshProxyTid)
+ contents, err := ioutil.ReadFile(tidFile)
+ if err != nil {
+ return 0, 0, "", err
+ }
+
+ var pid, tid uint32
+ fmt.Sscanf(string(contents), "%d:%d", &pid, &tid)
+ return pid, tid, tidFile, nil
+}
+
//nolint:cyclop
func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, func() error, error) {
var files []string
diff --git a/pkg/machine/wsl/util_windows.go b/pkg/machine/wsl/util_windows.go
index 95e4c9894..b5c28e015 100644
--- a/pkg/machine/wsl/util_windows.go
+++ b/pkg/machine/wsl/util_windows.go
@@ -67,6 +67,7 @@ const (
TOKEN_QUERY = 0x0008
SE_PRIVILEGE_ENABLED = 0x00000002
SE_ERR_ACCESSDENIED = 0x05
+ WM_QUIT = 0x12
)
func winVersionAtLeast(major uint, minor uint, build uint) bool {
@@ -279,6 +280,18 @@ func obtainShutdownPrivilege() error {
return nil
}
+func getProcessState(pid int) (active bool, exitCode int) {
+ const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
+ handle, err := syscall.OpenProcess(da, false, uint32(pid))
+ if err != nil {
+ return false, int(syscall.ERROR_PROC_NOT_FOUND)
+ }
+
+ var code uint32
+ syscall.GetExitCodeProcess(handle, &code)
+ return code == 259, int(code)
+}
+
func addRunOnceRegistryEntry(command string) error {
k, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\RunOnce`, registry.WRITE)
if err != nil {
@@ -336,3 +349,9 @@ func buildCommandArgs(elevate bool) string {
}
return strings.Join(args, " ")
}
+
+func sendQuit(tid uint32) {
+ user32 := syscall.NewLazyDLL("user32.dll")
+ postMessage := user32.NewProc("PostThreadMessageW")
+ postMessage.Call(uintptr(tid), WM_QUIT, 0, 0)
+}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 22f5041d0..a0b6edcfb 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -390,11 +390,11 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
return joinUserAndMountNS(uint(pid), "")
}
}
- return false, -1, errors.Wrapf(err, "error setting up the process")
+ return false, -1, errors.New("error setting up the process")
}
if b[0] != '0' {
- return false, -1, errors.Wrapf(err, "error setting up the process")
+ return false, -1, errors.New("error setting up the process")
}
signals := []os.Signal{}
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index fe220b9e8..a5772bc6a 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -47,17 +47,6 @@ func addPrivilegedDevices(g *generate.Generator) error {
if _, found := mounts[d.Path]; found {
continue
}
- st, err := os.Stat(d.Path)
- if err != nil {
- if err == unix.EPERM {
- continue
- }
- return err
- }
- // Skip devices that the user has not access to.
- if st.Mode()&0007 == 0 {
- continue
- }
newMounts = append(newMounts, devMnt)
}
g.Config.Mounts = append(newMounts, g.Config.Mounts...)
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 2fd149b49..475401016 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -4,7 +4,10 @@ import (
"context"
"encoding/json"
"fmt"
+ "math"
"net"
+ "regexp"
+ "strconv"
"strings"
"time"
@@ -291,9 +294,9 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
return nil, err
}
- // Only set the env if the value is not ""
- if value != "" {
- envs[env.Name] = value
+ // Only set the env if the value is not nil
+ if value != nil {
+ envs[env.Name] = *value
}
}
for _, envFrom := range opts.Container.EnvFrom {
@@ -609,7 +612,7 @@ func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string]
// envVarValue returns the environment variable value configured within the container's env setting.
// It gets the value from a configMap or secret if specified, otherwise returns env.Value
-func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
+func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
if env.ValueFrom != nil {
if env.ValueFrom.ConfigMapKeyRef != nil {
cmKeyRef := env.ValueFrom.ConfigMapKeyRef
@@ -618,16 +621,16 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
for _, c := range opts.ConfigMaps {
if cmKeyRef.Name == c.Name {
if value, ok := c.Data[cmKeyRef.Key]; ok {
- return value, nil
+ return &value, nil
}
err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name)
break
}
}
if cmKeyRef.Optional == nil || !*cmKeyRef.Optional {
- return "", err
+ return nil, err
}
- return "", nil
+ return nil, nil
}
if env.ValueFrom.SecretKeyRef != nil {
@@ -635,18 +638,123 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
secret, err := k8sSecretFromSecretManager(secKeyRef.Name, opts.SecretsManager)
if err == nil {
if val, ok := secret[secKeyRef.Key]; ok {
- return string(val), nil
+ value := string(val)
+ return &value, nil
}
err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key)
}
if secKeyRef.Optional == nil || !*secKeyRef.Optional {
- return "", errors.Errorf("Cannot set env %v: %v", env.Name, err)
+ return nil, errors.Errorf("Cannot set env %v: %v", env.Name, err)
}
- return "", nil
+ return nil, nil
+ }
+
+ if env.ValueFrom.FieldRef != nil {
+ return envVarValueFieldRef(env, opts)
+ }
+
+ if env.ValueFrom.ResourceFieldRef != nil {
+ return envVarValueResourceFieldRef(env, opts)
}
}
- return env.Value, nil
+ return &env.Value, nil
+}
+
+func envVarValueFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
+ fieldRef := env.ValueFrom.FieldRef
+
+ fieldPathLabelPattern := `^metadata.labels\['(.+)'\]$`
+ fieldPathLabelRegex := regexp.MustCompile(fieldPathLabelPattern)
+ fieldPathAnnotationPattern := `^metadata.annotations\['(.+)'\]$`
+ fieldPathAnnotationRegex := regexp.MustCompile(fieldPathAnnotationPattern)
+
+ fieldPath := fieldRef.FieldPath
+
+ if fieldPath == "metadata.name" {
+ return &opts.PodName, nil
+ }
+ if fieldPath == "metadata.uid" {
+ return &opts.PodID, nil
+ }
+ fieldPathMatches := fieldPathLabelRegex.FindStringSubmatch(fieldPath)
+ if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp
+ labelValue := opts.Labels[fieldPathMatches[1]] // not existent label is OK
+ return &labelValue, nil
+ }
+ fieldPathMatches = fieldPathAnnotationRegex.FindStringSubmatch(fieldPath)
+ if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp
+ annotationValue := opts.Annotations[fieldPathMatches[1]] // not existent annotation is OK
+ return &annotationValue, nil
+ }
+
+ return nil, errors.Errorf(
+ "Can not set env %v. Reason: fieldPath %v is either not valid or not supported",
+ env.Name, fieldPath,
+ )
+}
+
+func envVarValueResourceFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
+ divisor := env.ValueFrom.ResourceFieldRef.Divisor
+ if divisor.IsZero() { // divisor not set, use default
+ divisor.Set(1)
+ }
+
+ var value *resource.Quantity
+ resources := opts.Container.Resources
+ resourceName := env.ValueFrom.ResourceFieldRef.Resource
+ var isValidDivisor bool
+
+ switch resourceName {
+ case "limits.memory":
+ value = resources.Limits.Memory()
+ isValidDivisor = isMemoryDivisor(divisor)
+ case "limits.cpu":
+ value = resources.Limits.Cpu()
+ isValidDivisor = isCPUDivisor(divisor)
+ case "requests.memory":
+ value = resources.Requests.Memory()
+ isValidDivisor = isMemoryDivisor(divisor)
+ case "requests.cpu":
+ value = resources.Requests.Cpu()
+ isValidDivisor = isCPUDivisor(divisor)
+ default:
+ return nil, errors.Errorf(
+ "Can not set env %v. Reason: resource %v is either not valid or not supported",
+ env.Name, resourceName,
+ )
+ }
+
+ if !isValidDivisor {
+ return nil, errors.Errorf(
+ "Can not set env %s. Reason: divisor value %s is not valid",
+ env.Name, divisor.String(),
+ )
+ }
+
+ // k8s rounds up the result to the nearest integer
+ intValue := int(math.Ceil(value.AsApproximateFloat64() / divisor.AsApproximateFloat64()))
+ stringValue := strconv.Itoa(intValue)
+
+ return &stringValue, nil
+}
+
+func isMemoryDivisor(divisor resource.Quantity) bool {
+ switch divisor.String() {
+ case "1", "1k", "1M", "1G", "1T", "1P", "1E", "1Ki", "1Mi", "1Gi", "1Ti", "1Pi", "1Ei":
+ return true
+ default:
+ return false
+ }
+}
+
+func isCPUDivisor(divisor resource.Quantity) bool {
+ switch divisor.String() {
+ case "1", "1m":
+ return true
+ default:
+ return false
+ }
}
// getPodPorts converts a slice of kube container descriptions to an
diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go
index f714826f0..282324310 100644
--- a/pkg/specgen/generate/kube/play_test.go
+++ b/pkg/specgen/generate/kube/play_test.go
@@ -2,13 +2,17 @@ package kube
import (
"encoding/json"
+ "fmt"
"io/ioutil"
+ "math"
"os"
+ "strconv"
"testing"
"github.com/containers/common/pkg/secrets"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/resource"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -233,7 +237,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: configMapList,
},
false,
- "",
+ nilString,
},
{
"OptionalContainerKeyDoesNotExistInConfigMap",
@@ -253,7 +257,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: configMapList,
},
true,
- "",
+ nilString,
},
{
"ConfigMapDoesNotExist",
@@ -272,7 +276,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: configMapList,
},
false,
- "",
+ nilString,
},
{
"OptionalConfigMapDoesNotExist",
@@ -292,7 +296,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: configMapList,
},
true,
- "",
+ nilString,
},
{
"EmptyConfigMapList",
@@ -311,7 +315,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: []v1.ConfigMap{},
},
false,
- "",
+ nilString,
},
{
"OptionalEmptyConfigMapList",
@@ -331,7 +335,7 @@ func TestEnvVarValue(t *testing.T) {
ConfigMaps: []v1.ConfigMap{},
},
true,
- "",
+ nilString,
},
{
"SecretExists",
@@ -369,7 +373,7 @@ func TestEnvVarValue(t *testing.T) {
SecretsManager: secretsManager,
},
false,
- "",
+ nilString,
},
{
"OptionalContainerKeyDoesNotExistInSecret",
@@ -389,7 +393,7 @@ func TestEnvVarValue(t *testing.T) {
SecretsManager: secretsManager,
},
true,
- "",
+ nilString,
},
{
"SecretDoesNotExist",
@@ -408,7 +412,7 @@ func TestEnvVarValue(t *testing.T) {
SecretsManager: secretsManager,
},
false,
- "",
+ nilString,
},
{
"OptionalSecretDoesNotExist",
@@ -428,8 +432,268 @@ func TestEnvVarValue(t *testing.T) {
SecretsManager: secretsManager,
},
true,
+ nilString,
+ },
+ {
+ "FieldRefMetadataName",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.name",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ PodName: "test",
+ },
+ true,
+ "test",
+ },
+ {
+ "FieldRefMetadataUID",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.uid",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ PodID: "ec71ff37c67b688598c0008187ab0960dc34e1dfdcbf3a74e3d778bafcfe0977",
+ },
+ true,
+ "ec71ff37c67b688598c0008187ab0960dc34e1dfdcbf3a74e3d778bafcfe0977",
+ },
+ {
+ "FieldRefMetadataLabelsExist",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.labels['label']",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Labels: map[string]string{"label": "label"},
+ },
+ true,
+ "label",
+ },
+ {
+ "FieldRefMetadataLabelsEmpty",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.labels['label']",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Labels: map[string]string{"label": ""},
+ },
+ true,
+ "",
+ },
+ {
+ "FieldRefMetadataLabelsNotExist",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.labels['label']",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ true,
+ "",
+ },
+ {
+ "FieldRefMetadataAnnotationsExist",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.annotations['annotation']",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Annotations: map[string]string{"annotation": "annotation"},
+ },
+ true,
+ "annotation",
+ },
+ {
+ "FieldRefMetadataAnnotationsEmpty",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.annotations['annotation']",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Annotations: map[string]string{"annotation": ""},
+ },
+ true,
"",
},
+ {
+ "FieldRefMetadataAnnotationsNotExist",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.annotations['annotation']",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ true,
+ "",
+ },
+ {
+ "FieldRefInvalid1",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.annotations['annotation]",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "FieldRefInvalid2",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.dummy['annotation']",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "FieldRefNotSupported",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ FieldRef: &v1.ObjectFieldSelector{
+ FieldPath: "metadata.namespace",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "ResourceFieldRefNotSupported",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "limits.dummy",
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "ResourceFieldRefMemoryDivisorNotValid",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "limits.memory",
+ Divisor: resource.MustParse("2M"),
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "ResourceFieldRefCpuDivisorNotValid",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "limits.cpu",
+ Divisor: resource.MustParse("2m"),
+ },
+ },
+ },
+ CtrSpecGenOptions{},
+ false,
+ nilString,
+ },
+ {
+ "ResourceFieldRefNoDivisor",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "limits.memory",
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Container: container,
+ },
+ true,
+ memoryString,
+ },
+ {
+ "ResourceFieldRefMemoryDivisor",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "limits.memory",
+ Divisor: resource.MustParse("1Mi"),
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Container: container,
+ },
+ true,
+ strconv.Itoa(int(math.Ceil(float64(memoryInt) / 1024 / 1024))),
+ },
+ {
+ "ResourceFieldRefCpuDivisor",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ResourceFieldRef: &v1.ResourceFieldSelector{
+ Resource: "requests.cpu",
+ Divisor: resource.MustParse("1m"),
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ Container: container,
+ },
+ true,
+ strconv.Itoa(int(float64(cpuInt) / 0.001)),
+ },
}
for _, test := range tests {
@@ -437,59 +701,85 @@ func TestEnvVarValue(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
result, err := envVarValue(test.envVar, &test.options)
assert.Equal(t, err == nil, test.succeed)
- assert.Equal(t, test.expected, result)
+ if test.expected == nilString {
+ assert.Nil(t, result)
+ } else {
+ fmt.Println(*result, test.expected)
+ assert.Equal(t, &(test.expected), result)
+ }
})
}
}
-var configMapList = []v1.ConfigMap{
- {
- TypeMeta: v12.TypeMeta{
- Kind: "ConfigMap",
- },
- ObjectMeta: v12.ObjectMeta{
- Name: "bar",
- },
- Data: map[string]string{
- "myvar": "bar",
- },
- },
- {
- TypeMeta: v12.TypeMeta{
- Kind: "ConfigMap",
- },
- ObjectMeta: v12.ObjectMeta{
- Name: "foo",
+var (
+ nilString = "<nil>"
+ configMapList = []v1.ConfigMap{
+ {
+ TypeMeta: v12.TypeMeta{
+ Kind: "ConfigMap",
+ },
+ ObjectMeta: v12.ObjectMeta{
+ Name: "bar",
+ },
+ Data: map[string]string{
+ "myvar": "bar",
+ },
},
- Data: map[string]string{
- "myvar": "foo",
+ {
+ TypeMeta: v12.TypeMeta{
+ Kind: "ConfigMap",
+ },
+ ObjectMeta: v12.ObjectMeta{
+ Name: "foo",
+ },
+ Data: map[string]string{
+ "myvar": "foo",
+ },
},
- },
-}
+ }
-var optional = true
+ optional = true
-var k8sSecrets = []v1.Secret{
- {
- TypeMeta: v12.TypeMeta{
- Kind: "Secret",
- },
- ObjectMeta: v12.ObjectMeta{
- Name: "bar",
- },
- Data: map[string][]byte{
- "myvar": []byte("bar"),
- },
- },
- {
- TypeMeta: v12.TypeMeta{
- Kind: "Secret",
+ k8sSecrets = []v1.Secret{
+ {
+ TypeMeta: v12.TypeMeta{
+ Kind: "Secret",
+ },
+ ObjectMeta: v12.ObjectMeta{
+ Name: "bar",
+ },
+ Data: map[string][]byte{
+ "myvar": []byte("bar"),
+ },
},
- ObjectMeta: v12.ObjectMeta{
- Name: "foo",
+ {
+ TypeMeta: v12.TypeMeta{
+ Kind: "Secret",
+ },
+ ObjectMeta: v12.ObjectMeta{
+ Name: "foo",
+ },
+ Data: map[string][]byte{
+ "myvar": []byte("foo"),
+ },
},
- Data: map[string][]byte{
- "myvar": []byte("foo"),
+ }
+
+ cpuInt = 4
+ cpuString = strconv.Itoa(cpuInt)
+ memoryInt = 30000000
+ memoryString = strconv.Itoa(memoryInt)
+ container = v1.Container{
+ Name: "test",
+ Resources: v1.ResourceRequirements{
+ Limits: v1.ResourceList{
+ v1.ResourceCPU: resource.MustParse(cpuString),
+ v1.ResourceMemory: resource.MustParse(memoryString),
+ },
+ Requests: v1.ResourceList{
+ v1.ResourceCPU: resource.MustParse(cpuString),
+ v1.ResourceMemory: resource.MustParse(memoryString),
+ },
},
- },
-}
+ }
+)
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index e52d70092..01f731b60 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -122,7 +122,7 @@ func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, config
if configMap == nil {
// If the volumeSource was optional, move on even if a matching configmap wasn't found
- if *configMapVolumeSource.Optional {
+ if configMapVolumeSource.Optional != nil && *configMapVolumeSource.Optional {
kv.Source = configMapVolumeSource.Name
kv.Optional = *configMapVolumeSource.Optional
return kv, nil
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 672a53eea..68fda3ad7 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -82,7 +82,7 @@ func pullOrBuildInfraImage(p *entities.PodSpec, rt *libpod.Runtime) error {
imageName = rtConfig.Engine.InfraImage
}
- if imageName != config.DefaultInfraImage {
+ if imageName != "" {
_, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
if err != nil {
return err
@@ -281,8 +281,6 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
p.InfraContainerSpec.ConmonPidFile = p.InfraConmonPidFile
}
- if p.InfraImage != config.DefaultInfraImage {
- p.InfraContainerSpec.Image = p.InfraImage
- }
+ p.InfraContainerSpec.Image = p.InfraImage
return p.InfraContainerSpec, nil
}
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index 2eaf71897..9c6709905 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -246,7 +246,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
// Ignore net sysctls if --net=host
if s.NetNS.IsHost() && strings.HasPrefix(sysctlKey, "net.") {
- return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since Host Namespace set to host", sysctlKey, sysctlVal)
+ return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since Network Namespace set to host", sysctlKey, sysctlVal)
}
// Ignore uts sysctls if --uts=host
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index c1356bef4..e672bc65f 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -353,11 +353,11 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork
toReturn.NSMode = FromPod
case ns == "" || ns == string(Default) || ns == string(Private):
// Net defaults to Slirp on rootless
- if rootless.IsRootless() && containerConfig.Containers.RootlessNetworking != "cni" {
+ if rootless.IsRootless() {
toReturn.NSMode = Slirp
break
}
- // if not slirp we use bridge
+ // if root we use bridge
fallthrough
case ns == string(Bridge), strings.HasPrefix(ns, string(Bridge)+":"):
toReturn.NSMode = Bridge
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 7b1115f5d..759caa0c0 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -96,7 +96,7 @@ type PodNetworkConfig struct {
// Only available if NetNS is set to Bridge or Slirp.
// Optional.
PortMappings []types.PortMapping `json:"portmappings,omitempty"`
- // Map of networks names ot ids the container should join to.
+ // Map of networks names to ids the container should join to.
// You can request additional settings for each network, you can
// set network aliases, static ips, static mac address and the
// network interface name for this container on the specific network.
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 750fc875d..7f6f79b87 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -223,7 +223,7 @@ type ContainerStorageConfig struct {
// Conflicts with Image.
// At least one of Image or Rootfs must be specified.
Rootfs string `json:"rootfs,omitempty"`
- // RootfsOverlay tells if rootfs is actuall an overlay on top of base path
+ // RootfsOverlay tells if rootfs is actually an overlay on top of base path
RootfsOverlay bool `json:"rootfs_overlay,omitempty"`
// ImageVolumeMode indicates how image volumes will be created.
// Supported modes are "ignore" (do not create), "tmpfs" (create as
@@ -423,7 +423,7 @@ type ContainerNetworkConfig struct {
// PublishExposedPorts is set.
// Optional.
Expose map[uint16]string `json:"expose,omitempty"`
- // Map of networks names ot ids the container should join to.
+ // Map of networks names or ids that the container should join.
// You can request additional settings for each network, you can
// set network aliases, static ips, static mac address and the
// network interface name for this container on the specific network.
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index b6a18a274..17699a038 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/podman/v4/pkg/specgen"
systemdDefine "github.com/containers/podman/v4/pkg/systemd/define"
"github.com/containers/podman/v4/pkg/util"
+ "github.com/docker/docker/opts"
"github.com/docker/go-units"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -422,11 +423,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
// SHM Size
if c.ShmSize != "" {
- shmSize, err := units.FromHumanSize(c.ShmSize)
- if err != nil {
+ var m opts.MemBytes
+ if err := m.Set(c.ShmSize); err != nil {
return errors.Wrapf(err, "unable to translate --shm-size")
}
- s.ShmSize = &shmSize
+ val := m.Value()
+ s.ShmSize = &val
}
if c.Net != nil {
@@ -893,7 +895,7 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error)
source = kv[1]
case "type":
if secretType != "" {
- return nil, nil, errors.Wrap(secretParseError, "cannot set more tha one secret type")
+ return nil, nil, errors.Wrap(secretParseError, "cannot set more than one secret type")
}
if kv[1] != "mount" && kv[1] != "env" {
return nil, nil, errors.Wrapf(secretParseError, "type %s is invalid", kv[1])
diff --git a/pkg/specgenutil/util.go b/pkg/specgenutil/util.go
index 0a980a576..80d31398b 100644
--- a/pkg/specgenutil/util.go
+++ b/pkg/specgenutil/util.go
@@ -279,7 +279,7 @@ func CreateExitCommandArgs(storageConfig storageTypes.StoreOptions, config *conf
"--log-level", logrus.GetLevel().String(),
"--cgroup-manager", config.Engine.CgroupManager,
"--tmpdir", config.Engine.TmpDir,
- "--cni-config-dir", config.Network.NetworkConfigDir,
+ "--network-config-dir", config.Network.NetworkConfigDir,
"--network-backend", config.Network.NetworkBackend,
}
if config.Engine.OCIRuntime != "" {
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index fd5c247f3..ea829c810 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -94,6 +94,13 @@ type containerInfo struct {
RunRoot string
// Add %i and %I to description and execute parts
IdentifySpecifier bool
+ // Wants are the list of services that this service is (weak) dependent on. This
+ // option does not influence the order in which services are started or stopped.
+ Wants []string
+ // After ordering dependencies between the list of services and this service.
+ After []string
+ // Similar to Wants, but declares a stronger requirement dependency.
+ Requires []string
}
const containerTemplate = headerTemplate + `
@@ -101,6 +108,19 @@ const containerTemplate = headerTemplate + `
BindsTo={{{{- range $index, $value := .BoundToServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}}
After={{{{- range $index, $value := .BoundToServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}}
{{{{- end}}}}
+{{{{- if or .Wants .After .Requires }}}}
+
+# User-defined dependencies
+{{{{- end}}}}
+{{{{- if .Wants}}}}
+Wants={{{{- range $index, $value := .Wants }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
+{{{{- if .After}}}}
+After={{{{- range $index, $value := .After }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
+{{{{- if .Requires}}}}
+Requires={{{{- range $index, $value := .Requires }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
[Service]
Environment={{{{.EnvVariable}}}}=%n{{{{- if (eq .IdentifySpecifier true) }}}}-%i{{{{- end}}}}
@@ -201,6 +221,9 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste
CreateCommand: createCommand,
RunRoot: runRoot,
containerEnv: envs,
+ Wants: options.Wants,
+ After: options.After,
+ Requires: options.Requires,
}
return &info, nil
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 45bb5173a..2f653a4b9 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -91,6 +91,116 @@ Type=forking
WantedBy=default.target
`
+ goodNameCustomWants := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+# User-defined dependencies
+Wants=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+ExecStopPost=/usr/bin/podman stop -t 10 foobar
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
+ goodNameCustomAfter := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+# User-defined dependencies
+After=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+ExecStopPost=/usr/bin/podman stop -t 10 foobar
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
+ goodNameCustomRequires := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+# User-defined dependencies
+Requires=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+ExecStopPost=/usr/bin/podman stop -t 10 foobar
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
+ goodNameCustomDependencies := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+
+# User-defined dependencies
+Wants=a.service b.service c.target
+After=a.service b.service c.target
+Requires=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=70
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+ExecStopPost=/usr/bin/podman stop -t 10 foobar
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
goodNameBoundTo := `# container-foobar.service
# autogenerated by Podman CI
@@ -613,6 +723,84 @@ WantedBy=default.target
false,
false,
},
+ {"good with name and wants",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ Wants: []string{"a.service", "b.service", "c.target"},
+ EnvVariable: define.EnvVariable,
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ },
+ goodNameCustomWants,
+ false,
+ false,
+ false,
+ false,
+ },
+ {"good with name and after",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ After: []string{"a.service", "b.service", "c.target"},
+ EnvVariable: define.EnvVariable,
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ },
+ goodNameCustomAfter,
+ false,
+ false,
+ false,
+ false,
+ },
+ {"good with name and requires",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ Requires: []string{"a.service", "b.service", "c.target"},
+ EnvVariable: define.EnvVariable,
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ },
+ goodNameCustomRequires,
+ false,
+ false,
+ false,
+ false,
+ },
+ {"good with name and dependencies",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ Wants: []string{"a.service", "b.service", "c.target"},
+ After: []string{"a.service", "b.service", "c.target"},
+ Requires: []string{"a.service", "b.service", "c.target"},
+ EnvVariable: define.EnvVariable,
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ },
+ goodNameCustomDependencies,
+ false,
+ false,
+ false,
+ false,
+ },
{"good with name and bound to",
containerInfo{
Executable: "/usr/bin/podman",
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 17e1dc5a2..003c23e77 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -83,10 +83,30 @@ type podInfo struct {
RunRoot string
// Add %i and %I to description and execute parts - this should not be used
IdentifySpecifier bool
+ // Wants are the list of services that this service is (weak) dependent on. This
+ // option does not influence the order in which services are started or stopped.
+ Wants []string
+ // After ordering dependencies between the list of services and this service.
+ After []string
+ // Similar to Wants, but declares a stronger requirement dependency.
+ Requires []string
}
const podTemplate = headerTemplate + `Requires={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}}
Before={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}}
+{{{{- if or .Wants .After .Requires }}}}
+
+# User-defined dependencies
+{{{{- end}}}}
+{{{{- if .Wants}}}}
+Wants={{{{- range $index, $value := .Wants }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
+{{{{- if .After}}}}
+After={{{{- range $index, $value := .After }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
+{{{{- if .Requires}}}}
+Requires={{{{- range $index, $value := .Requires }}}}{{{{ if $index}}}} {{{{end}}}}{{{{ $value }}}}{{{{end}}}}
+{{{{- end}}}}
[Service]
Environment={{{{.EnvVariable}}}}=%n
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 6c84c8895..b37e0825b 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -67,6 +67,121 @@ WantedBy=default.target
podGood := serviceInfo + headerInfo + podContent
podGoodNoHeaderInfo := serviceInfo + podContent
+ podGoodCustomWants := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+# User-defined dependencies
+Wants=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+ podGoodCustomAfter := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+# User-defined dependencies
+After=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+ podGoodCustomRequires := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+# User-defined dependencies
+Requires=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+ podGoodCustomDependencies := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+# User-defined dependencies
+Wants=a.service b.service c.target
+After=a.service b.service c.target
+Requires=a.service b.service c.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
podGoodRestartSec := `# pod-123abc.service
# autogenerated by Podman CI
@@ -232,6 +347,94 @@ WantedBy=default.target
false,
false,
},
+ {"pod",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ Wants: []string{"a.service", "b.service", "c.target"},
+ CreateCommand: []string{
+ "podman", "pod", "create", "--name", "foo", "--wants", "a.service",
+ "--wants", "b.service", "--wants", "c.target", "bar=arg with space"},
+ },
+ podGoodCustomWants,
+ false,
+ false,
+ false,
+ },
+ {"pod",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ After: []string{"a.service", "b.service", "c.target"},
+ CreateCommand: []string{
+ "podman", "pod", "create", "--name", "foo", "--after", "a.service",
+ "--after", "b.service", "--after", "c.target", "bar=arg with space"},
+ },
+ podGoodCustomAfter,
+ false,
+ false,
+ false,
+ },
+ {"pod",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ Requires: []string{"a.service", "b.service", "c.target"},
+ CreateCommand: []string{
+ "podman", "pod", "create", "--name", "foo", "--requires", "a.service",
+ "--requires", "b.service", "--requires", "c.target", "bar=arg with space"},
+ },
+ podGoodCustomRequires,
+ false,
+ false,
+ false,
+ },
+ {"pod",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ Wants: []string{"a.service", "b.service", "c.target"},
+ After: []string{"a.service", "b.service", "c.target"},
+ Requires: []string{"a.service", "b.service", "c.target"},
+ CreateCommand: []string{
+ "podman", "pod", "create", "--name", "foo", "--wants", "a.service",
+ "--wants", "b.service", "--wants", "c.target", "--after", "a.service",
+ "--after", "b.service", "--after", "c.target", "--requires", "a.service",
+ "--requires", "b.service", "--requires", "c.target", "bar=arg with space"},
+ },
+ podGoodCustomDependencies,
+ false,
+ false,
+ false,
+ },
{"pod restartSec",
podInfo{
Executable: "/usr/bin/podman",
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index 959763dba..f32cf6ea6 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -25,16 +25,30 @@ type defaultMountOptions struct {
// The sourcePath variable, if not empty, contains a bind mount source.
func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string, error) {
var (
- foundWrite, foundSize, foundProp, foundMode, foundExec, foundSuid, foundDev, foundCopyUp, foundBind, foundZ, foundU bool
+ foundWrite, foundSize, foundProp, foundMode, foundExec, foundSuid, foundDev, foundCopyUp, foundBind, foundZ, foundU, foundOverlay bool
)
newOptions := make([]string, 0, len(options))
for _, opt := range options {
// Some options have parameters - size, mode
splitOpt := strings.SplitN(opt, "=", 2)
+
+ // add advanced options such as upperdir=/path and workdir=/path, when overlay is specified
+ if foundOverlay {
+ if strings.Contains(opt, "upperdir") {
+ newOptions = append(newOptions, opt)
+ continue
+ }
+ if strings.Contains(opt, "workdir") {
+ newOptions = append(newOptions, opt)
+ continue
+ }
+ }
+
switch splitOpt[0] {
- case "idmap":
case "O":
+ foundOverlay = true
+ case "idmap":
if len(options) > 1 {
return nil, errors.Wrapf(ErrDupeMntOption, "'O' option can not be used with other options")
}
diff --git a/podman.spec.rpkg b/podman.spec.rpkg
index 5c203b24a..d02b7ea99 100644
--- a/podman.spec.rpkg
+++ b/podman.spec.rpkg
@@ -77,12 +77,15 @@ BuildRequires: ostree-devel
BuildRequires: systemd
BuildRequires: systemd-devel
Requires: conmon >= 2:2.0.30-2
-Requires: containers-common >= 4:1-30
-Requires: containernetworking-plugins >= 1.0.0-15.1
+# containers-common pulled from podman-next copr for f34,
+# from the distro repos for f35+
+%if 0%{?fedora} <= 35
+Requires: containers-common >= 4:1-39
+%else
+Requires: containers-common >= 4:1-46
+%endif
Requires: iptables
Requires: nftables
-Requires: netavark
-Recommends: %{name}-plugins = %{epoch}:%{version}-%{release}
Recommends: catatonit
Suggests: qemu-user-static
@@ -196,13 +199,13 @@ make docs docker-docs
# the installable rpm package.
%install
PODMAN_VERSION=%{version} %{__make} DESTDIR=%{buildroot} PREFIX=%{_prefix} ETCDIR=%{buildroot}%{_sysconfdir} \
- install.bin-nobuild \
- install.man-nobuild \
+ install.bin \
+ install.man \
install.systemd \
install.completions \
install.docker \
- install.docker-docs-nobuild \
- install.remote-nobuild \
+ install.docker-docs \
+ install.remote \
install -d -p %{buildroot}/%{_datadir}/%{name}/test/system
cp -pav test/system %{buildroot}/%{_datadir}/%{name}/test/
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 36c2fc6aa..673858a3c 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -197,6 +197,14 @@ t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR 200 \
t POST libpod/images/prune 200
t POST libpod/images/prune 200 length=0 []
+# compat api must allow loading tar which contain multiple images
+podman pull quay.io/libpod/alpine:latest quay.io/libpod/busybox:latest
+podman save -o ${TMPD}/test.tar quay.io/libpod/alpine:latest quay.io/libpod/busybox:latest
+t POST "images/load" ${TMPD}/test.tar 200 \
+ .stream="Loaded image: quay.io/libpod/busybox:latest,quay.io/libpod/alpine:latest"
+t GET libpod/images/quay.io/libpod/alpine:latest/exists 204
+t GET libpod/images/quay.io/libpod/busybox:latest/exists 204
+
cleanBuildTest
# vim: filetype=sh
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 72003984f..cc5eda88e 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -18,6 +18,14 @@ podman rm -a -f &>/dev/null
t GET "libpod/containers/json (at start: clean slate)" 200 length=0
+# Regression test for #12904 (race condition in logging code)
+mytext="hi-there-$(random_string 15)"
+podman run --rm -d --replace --name foo $IMAGE sh -c "echo $mytext;sleep 42"
+# Logs output is prepended by ^A^X
+t POST "containers/foo/attach?logs=true&stream=false" 200 \
+ $'\001\030'$mytext
+t POST "containers/foo/kill" 204
+
podman run -v /tmp:/tmp $IMAGE true
t GET libpod/containers/json 200 length=0
@@ -231,11 +239,16 @@ t GET containers/$cid/json 200 \
t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \
.Id~[0-9a-f]\\{64\\}
cid_top=$(jq -r '.Id' <<<"$output")
+# .Network is N/A when rootless
+network_expect=
+if root; then
+ network_expect='.NetworkSettings.Networks.podman.NetworkID=podman'
+fi
t GET containers/${cid_top}/json 200 \
.Config.Entrypoint[0]="top" \
.Config.Cmd='[]' \
.Path="top" \
- .NetworkSettings.Networks.podman.NetworkID=podman
+ $network_expect
t POST containers/${cid_top}/start 204
# make sure the container is running
t GET containers/${cid_top}/json 200 \
@@ -359,11 +372,15 @@ t GET containers/$cid/json 200 \
t DELETE containers/$cid?v=true 204
# Test Compat Create with default network mode (#10569)
+networkmode=slirp4netns
+if root; then
+ networkmode=bridge
+fi
t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \
.Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
- .HostConfig.NetworkMode="bridge"
+ .HostConfig.NetworkMode="$networkmode"
t DELETE containers/$cid?v=true 204
@@ -403,3 +420,29 @@ t GET containers/$cid/json 200 \
.HostConfig.Binds[0]~/tmp:/mnt:.* \
t DELETE containers/$cid?v=true 204
+
+# test apiv2 create/commit
+t POST containers/create \
+ Image=$IMAGE \
+ Entrypoint='["echo"]' \
+ Cmd='["param1","param2"]' \
+ 201 \
+ .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+
+# No such container
+t POST "commit?container=nonesuch" 404
+
+cparam="repo=newrepo&tag=v3&comment=abcd&author=eric"
+cparam="$cparam&format=docker&changes=CMD%20/bin/bar%0aEXPOSE%209090"
+t POST "commit?container=${cid:0:12}&$cparam" 201 \
+ .Id~[0-9a-f]\\{64\\}
+iid=$(jq -r '.Id' <<<"$output")
+t GET images/$iid/json 200 \
+ .RepoTags[0]=docker.io/library/newrepo:v3 \
+ .Config.ExposedPorts~.*"9090/tcp" \
+ .Config.Cmd~.*"/bin/bar" \
+ .Comment="abcd"
+
+t DELETE containers/$cid 204
+t DELETE images/docker.io/library/newrepo:v3?force=false 200
diff --git a/test/apiv2/python/rest_api/fixtures/podman.py b/test/apiv2/python/rest_api/fixtures/podman.py
index bae04f87d..c700571b9 100644
--- a/test/apiv2/python/rest_api/fixtures/podman.py
+++ b/test/apiv2/python/rest_api/fixtures/podman.py
@@ -44,7 +44,7 @@ class Podman:
os.environ["CNI_CONFIG_PATH"] = os.path.join(self.anchor_directory, "cni", "net.d")
os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True)
- self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"])
+ self.cmd.append("--network-config-dir=" + os.environ["CNI_CONFIG_PATH"])
cni_cfg = os.path.join(os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist")
# json decoded and encoded to ensure legal json
buf = json.loads(
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py
index 1b4597cf8..0386116a8 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_container.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py
@@ -130,7 +130,7 @@ class ContainerTestCase(APITestCase):
def test_attach(self):
self.skipTest("FIXME: Test timeouts")
- r = requests.post(self.uri(self.resolve_container("/containers/{}/attach")), timeout=5)
+ r = requests.post(self.uri(self.resolve_container("/containers/{}/attach?logs=true")), timeout=5)
self.assertIn(r.status_code, (101, 500), r.text)
def test_logs(self):
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index 19e8c12d0..56280f04e 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -45,8 +45,14 @@ echo 0 >$failures_file
# Where the tests live
TESTS_DIR=$(realpath $(dirname $0))
+# As of 2021-11 podman has one external helper binary, rootlessport, needed
+# for rootless networking.
+if [[ -z "$CONTAINERS_HELPER_BINARY_DIR" ]]; then
+ export CONTAINERS_HELPER_BINARY_DIR=$(realpath ${TESTS_DIR}/../../bin)
+fi
+
# Path to podman binary
-PODMAN_BIN=${PODMAN:-${TESTS_DIR}/../../bin/podman}
+PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman}
# Cleanup handlers
clean_up_server() {
@@ -289,7 +295,8 @@ function t() {
output="[$(file --brief $WORKDIR/curl.result.out)]"
echo "$output" >>$LOG
elif [[ -e $WORKDIR/curl.result.out ]]; then
- output=$(< $WORKDIR/curl.result.out)
+ # Output from /logs sometimes includes NULs. Strip them.
+ output=$(tr -d '\0' < $WORKDIR/curl.result.out)
if [[ $content_type =~ application/json ]] && [[ $method != "HEAD" ]]; then
jq . <<<"$output" >>$LOG
diff --git a/test/compose/test-compose b/test/compose/test-compose
index beaf276fd..7c4bf2e91 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -220,7 +220,7 @@ function start_service() {
--root $WORKDIR/root \
--runroot $WORKDIR/runroot \
--cgroup-manager=systemd \
- --cni-config-dir $WORKDIR/cni \
+ --network-config-dir $WORKDIR/cni \
system service \
--time 0 unix://$DOCKER_SOCK \
&> $WORKDIR/server.log &
@@ -247,7 +247,7 @@ function podman() {
--storage-driver=vfs \
--root $WORKDIR/root \
--runroot $WORKDIR/runroot \
- --cni-config-dir $WORKDIR/cni \
+ --network-config-dir $WORKDIR/cni \
"$@")
echo -n "$output" >>$WORKDIR/output.log
}
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 5dabe728a..a1c2f5e54 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -100,7 +100,7 @@ var _ = Describe("Podman build", func() {
It("podman build with logfile", func() {
logfile := filepath.Join(podmanTest.TempDir, "logfile")
- session := podmanTest.Podman([]string{"build", "--pull-never", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
+ session := podmanTest.Podman([]string{"build", "--pull=never", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -123,7 +123,7 @@ var _ = Describe("Podman build", func() {
// If the context directory is pointing at a file and not a directory,
// that's a no no, fail out.
It("podman build context directory a file", func() {
- session := podmanTest.Podman([]string{"build", "--pull-never", "build/context_dir_a_file"})
+ session := podmanTest.Podman([]string{"build", "--pull=never", "build/context_dir_a_file"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(125))
})
@@ -308,6 +308,30 @@ RUN exit 5`, ALPINE)
Expect(data).To(ContainSubstring(buildah.Version))
})
+ It("podman build and check identity with always", func() {
+ // with --pull=always
+ session := podmanTest.Podman([]string{"build", "--pull=always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test1", "build/basicalpine"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // Verify that OS and Arch are being set
+ inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test1"})
+ inspect.WaitWithDefaultTimeout()
+ data := inspect.OutputToString()
+ Expect(data).To(ContainSubstring(buildah.Version))
+
+ // with --pull-always
+ session = podmanTest.Podman([]string{"build", "--pull-always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test2", "build/basicalpine"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // Verify that OS and Arch are being set
+ inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test2"})
+ inspect.WaitWithDefaultTimeout()
+ data = inspect.OutputToString()
+ Expect(data).To(ContainSubstring(buildah.Version))
+ })
+
It("podman remote test container/docker file is not inside context dir", func() {
// Given
// Switch to temp dir and restore it afterwards
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 64f40d2ed..f843a8984 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"math/rand"
+ "net"
"os"
"os/exec"
"path/filepath"
@@ -46,7 +47,7 @@ type PodmanTestIntegration struct {
PodmanTest
ConmonBinary string
Root string
- CNIConfigDir string
+ NetworkConfigDir string
OCIRuntime string
RunRoot string
StorageOptions string
@@ -199,6 +200,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
host := GetHostDistributionInfo()
cwd, _ := os.Getwd()
+ root := filepath.Join(tempDir, "root")
podmanBinary := filepath.Join(cwd, "../../bin/podman")
if os.Getenv("PODMAN_BINARY") != "" {
podmanBinary = os.Getenv("PODMAN_BINARY")
@@ -235,11 +237,26 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
ociRuntime = "crun"
}
os.Setenv("DISABLE_HC_SYSTEMD", "true")
- CNIConfigDir := "/etc/cni/net.d"
+
+ networkBackend := CNI
+ networkConfigDir := "/etc/cni/net.d"
if rootless.IsRootless() {
- CNIConfigDir = filepath.Join(os.Getenv("HOME"), ".config/cni/net.d")
+ networkConfigDir = filepath.Join(os.Getenv("HOME"), ".config/cni/net.d")
+ }
+
+ if strings.ToLower(os.Getenv("NETWORK_BACKEND")) == "netavark" {
+ networkBackend = Netavark
+ networkConfigDir = "/etc/containers/networks"
+ if rootless.IsRootless() {
+ networkConfigDir = filepath.Join(root, "etc", "networks")
+ }
+ }
+
+ if err := os.MkdirAll(root, 0755); err != nil {
+ panic(err)
}
- if err := os.MkdirAll(CNIConfigDir, 0755); err != nil {
+
+ if err := os.MkdirAll(networkConfigDir, 0755); err != nil {
panic(err)
}
@@ -251,7 +268,6 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
storageFs = os.Getenv("STORAGE_FS")
storageOptions = "--storage-driver " + storageFs
}
-
p := &PodmanTestIntegration{
PodmanTest: PodmanTest{
PodmanBinary: podmanBinary,
@@ -260,11 +276,12 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
RemoteTest: remote,
ImageCacheFS: storageFs,
ImageCacheDir: ImageCacheDir,
+ NetworkBackend: networkBackend,
},
ConmonBinary: conmonBinary,
- Root: filepath.Join(tempDir, "root"),
+ Root: root,
TmpDir: tempDir,
- CNIConfigDir: CNIConfigDir,
+ NetworkConfigDir: networkConfigDir,
OCIRuntime: ociRuntime,
RunRoot: filepath.Join(tempDir, "runroot"),
StorageOptions: storageOptions,
@@ -719,6 +736,14 @@ func SkipIfRemote(reason string) {
Skip("[remote]: " + reason)
}
+func SkipIfNotRemote(reason string) {
+ checkReason(reason)
+ if IsRemote() {
+ return
+ }
+ Skip("[local]: " + reason)
+}
+
// SkipIfInContainer skips a test if the test is run inside a container
func SkipIfInContainer(reason string) {
checkReason(reason)
@@ -746,6 +771,18 @@ func SkipIfNotActive(unit string, reason string) {
}
}
+func SkipIfNetavark(p *PodmanTestIntegration) {
+ if p.NetworkBackend == Netavark {
+ Skip("This test is not compatible with the netavark network backend")
+ }
+}
+
+func SkipUntilAardvark(p *PodmanTestIntegration) {
+ if p.NetworkBackend == Netavark {
+ Skip("Re-enable when aardvark is functional")
+ }
+}
+
// PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment
func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration {
podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil, nil)
@@ -807,7 +844,9 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
if p.RemoteTest {
return args
}
- var debug string
+ var (
+ debug string
+ )
if _, ok := os.LookupEnv("DEBUG"); ok {
debug = "--log-level=debug --syslog=true "
}
@@ -817,12 +856,19 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
eventsType = "none"
}
- podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s",
- debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
+ networkBackend := p.NetworkBackend.ToString()
+ networkDir := p.NetworkConfigDir
+ if p.NetworkBackend == Netavark {
+ networkDir = p.NetworkConfigDir
+ }
+ podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s",
+ debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.CgroupManager, p.TmpDir, eventsType), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
+ podmanOptions = append(podmanOptions, "--network-backend", networkBackend)
+
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
if !noCache {
cacheOptions := []string{"--storage-opt",
@@ -834,6 +880,11 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
}
func writeConf(conf []byte, confPath string) {
+ if _, err := os.Stat(filepath.Dir(confPath)); os.IsNotExist(err) {
+ if err := os.MkdirAll(filepath.Dir(confPath), 777); err != nil {
+ fmt.Println(err)
+ }
+ }
if err := ioutil.WriteFile(confPath, conf, 777); err != nil {
fmt.Println(err)
}
@@ -848,10 +899,15 @@ func removeConf(confPath string) {
// generateNetworkConfig generates a cni config with a random name
// it returns the network name and the filepath
func generateNetworkConfig(p *PodmanTestIntegration) (string, string) {
+ var (
+ path string
+ conf string
+ )
// generate a random name to prevent conflicts with other tests
name := "net" + stringid.GenerateNonCryptoID()
- path := filepath.Join(p.CNIConfigDir, fmt.Sprintf("%s.conflist", name))
- conf := fmt.Sprintf(`{
+ if p.NetworkBackend != Netavark {
+ path = filepath.Join(p.NetworkConfigDir, fmt.Sprintf("%s.conflist", name))
+ conf = fmt.Sprintf(`{
"cniVersion": "0.3.0",
"name": "%s",
"plugins": [
@@ -876,12 +932,35 @@ func generateNetworkConfig(p *PodmanTestIntegration) (string, string) {
}
]
}`, name)
+ } else {
+ path = filepath.Join(p.NetworkConfigDir, fmt.Sprintf("%s.json", name))
+ conf = fmt.Sprintf(`
+{
+ "name": "%s",
+ "id": "e1ef2749024b88f5663ca693a9118e036d6bfc48bcfe460faf45e9614a513e5c",
+ "driver": "bridge",
+ "network_interface": "netavark1",
+ "created": "2022-01-05T14:15:10.975493521-06:00",
+ "subnets": [
+ {
+ "subnet": "10.100.0.0/16",
+ "gateway": "10.100.0.1"
+ }
+ ],
+ "ipv6_enabled": false,
+ "internal": false,
+ "dns_enabled": true,
+ "ipam_options": {
+ "driver": "host-local"
+ }
+}
+`, name)
+ }
writeConf([]byte(conf), path)
-
return name, path
}
-func (p *PodmanTestIntegration) removeCNINetwork(name string) {
+func (p *PodmanTestIntegration) removeNetwork(name string) {
session := p.Podman([]string{"network", "rm", "-f", name})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(BeNumerically("<=", 1), "Exit code must be 0 or 1")
@@ -929,3 +1008,33 @@ func writeYaml(content string, fileName string) error {
return nil
}
+
+// GetPort finds an unused port on the system
+func GetPort() int {
+ a, err := net.ResolveTCPAddr("tcp", "localhost:0")
+ if err != nil {
+ Fail(fmt.Sprintf("unable to get free port: %v", err))
+ }
+
+ l, err := net.ListenTCP("tcp", a)
+ if err != nil {
+ Fail(fmt.Sprintf("unable to get free port: %v", err))
+ }
+ defer l.Close()
+ return l.Addr().(*net.TCPAddr).Port
+}
+
+func ncz(port int) bool {
+ timeout := 500 * time.Millisecond
+ for i := 0; i < 5; i++ {
+ ncCmd := []string{"-z", "localhost", fmt.Sprintf("%d", port)}
+ fmt.Printf("Running: nc %s\n", strings.Join(ncCmd, " "))
+ check := SystemExec("nc", ncCmd)
+ if check.ExitCode() == 0 {
+ return true
+ }
+ time.Sleep(timeout)
+ timeout++
+ }
+ return false
+}
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index 57279ae9c..bfed01854 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -11,10 +11,11 @@ import (
. "github.com/containers/podman/v4/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gbytes"
. "github.com/onsi/gomega/gexec"
)
-var _ = Describe("Podman run", func() {
+var _ = Describe("Verify podman containers.conf usage", func() {
var (
tempdir string
err error
@@ -43,9 +44,9 @@ var _ = Describe("Podman run", func() {
os.Unsetenv("CONTAINERS_CONF")
})
- It("podman run limits test", func() {
+ It("limits test", func() {
SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users")
- //containers.conf is set to "nofile=500:500"
+ // containers.conf is set to "nofile=500:500"
session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -57,33 +58,41 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(ContainSubstring("2048"))
})
- It("podman run with containers.conf having additional env", func() {
- //containers.conf default env includes foo
+ It("having additional env", func() {
+ // containers.conf default env includes foo
session := podmanTest.Podman([]string{"run", ALPINE, "printenv"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("foo=bar"))
})
- It("podman run with additional devices", func() {
- //containers.conf devices includes notone
+ It("additional devices", func() {
+ // containers.conf devices includes notone
session := podmanTest.Podman([]string{"run", "--device", "/dev/null:/dev/bar", ALPINE, "ls", "/dev"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("bar"))
- Expect(session.OutputToString()).To(ContainSubstring("notone"))
+ Expect(session.OutputToString()).To(
+ And(
+ ContainSubstring("bar"),
+ ContainSubstring("notone"),
+ ))
})
- It("podman run shm-size", func() {
- //containers.conf default sets shm-size=201k, which ends up as 200k
+ It("shm-size", func() {
+ // containers.conf default sets shm-size=201k, which ends up as 200k
session := podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("size=200k"))
+
+ session = podmanTest.Podman([]string{"run", "--shm-size", "1g", ALPINE, "grep", "shm", "/proc/self/mounts"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("size=1048576k"))
})
- It("podman Capabilities in containers.conf", func() {
- SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1")
+ It("add capabilities", func() {
+ SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1")
cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"})
cap.WaitWithDefaultTimeout()
Expect(cap).Should(Exit(0))
@@ -98,17 +107,20 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).ToNot(Equal(cap.OutputToString()))
})
- It("podman Regular capabilities", func() {
+ It("regular capabilities", func() {
setup := podmanTest.RunTopContainer("test1")
setup.WaitWithDefaultTimeout()
result := podmanTest.Podman([]string{"top", "test1", "capeff"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("SYS_CHROOT"))
- Expect(result.OutputToString()).To(ContainSubstring("NET_RAW"))
+ Expect(result.Out.Contents()).To(
+ And(
+ ContainSubstring("SYS_CHROOT"),
+ ContainSubstring("NET_RAW"),
+ ))
})
- It("podman drop capabilities", func() {
+ It("drop capabilities", func() {
os.Setenv("CONTAINERS_CONF", "config/containers-caps.conf")
if IsRemote() {
podmanTest.RestartRemoteService()
@@ -118,8 +130,11 @@ var _ = Describe("Podman run", func() {
result := podmanTest.Podman([]string{"container", "top", "test1", "capeff"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).ToNot(ContainSubstring("SYS_CHROOT"))
- Expect(result.OutputToString()).ToNot(ContainSubstring("NET_RAW"))
+ Expect(result.Out.Contents()).ToNot(
+ And(
+ ContainSubstring("SYS_CHROOT"),
+ ContainSubstring("NET_RAW"),
+ ))
})
verifyNSHandling := func(nspath, option string) {
@@ -128,7 +143,7 @@ var _ = Describe("Podman run", func() {
if IsRemote() {
podmanTest.RestartRemoteService()
}
- //containers.conf default ipcns to default to host
+ // containers.conf default ipcns to default to host
session := podmanTest.Podman([]string{"run", ALPINE, "ls", "-l", nspath})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -137,7 +152,7 @@ var _ = Describe("Podman run", func() {
cmd := exec.Command("ls", "-l", nspath)
res, err := cmd.Output()
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
fields = strings.Split(string(res), " ")
hostNS := strings.TrimSuffix(fields[len(fields)-1], "\n")
Expect(hostNS).To(Equal(ctrNS))
@@ -148,23 +163,23 @@ var _ = Describe("Podman run", func() {
Expect(hostNS).ToNot(Equal(ctrNS))
}
- It("podman compare netns", func() {
+ It("netns", func() {
verifyNSHandling("/proc/self/ns/net", "--network")
})
- It("podman compare ipcns", func() {
+ It("ipcns", func() {
verifyNSHandling("/proc/self/ns/ipc", "--ipc")
})
- It("podman compare utsns", func() {
+ It("utsns", func() {
verifyNSHandling("/proc/self/ns/uts", "--uts")
})
- It("podman compare pidns", func() {
+ It("pidns", func() {
verifyNSHandling("/proc/self/ns/pid", "--pid")
})
- It("podman compare cgroupns", func() {
+ It("cgroupns", func() {
verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns")
})
@@ -185,17 +200,17 @@ var _ = Describe("Podman run", func() {
cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", fmt.Sprintf("CONTAINER_ID_FULL=%s", cid))
out, err := cmd.CombinedOutput()
- Expect(err).To(BeNil())
- Expect(string(out)).To(ContainSubstring("alpine"))
+ Expect(err).ToNot(HaveOccurred())
+ Expect(out).To(ContainSubstring("alpine"))
})
- It("podman containers.conf additionalvolumes", func() {
+ It("add volumes", func() {
conffile := filepath.Join(podmanTest.TempDir, "container.conf")
tempdir, err = CreateTempDirInTempDir()
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", tempdir, tempdir)), 0755)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
os.Setenv("CONTAINERS_CONF", conffile)
if IsRemote() {
@@ -206,8 +221,8 @@ var _ = Describe("Podman run", func() {
Expect(result).Should(Exit(0))
})
- It("podman run containers.conf sysctl test", func() {
- //containers.conf is set to "net.ipv4.ping_group_range=0 1000"
+ It("sysctl test", func() {
+ // containers.conf is set to "net.ipv4.ping_group_range=0 1000"
session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -220,47 +235,49 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).ToNot((ContainSubstring("1000")))
})
- It("podman run containers.conf search domain", func() {
+ It("search domain", func() {
session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search foobar.com")))
})
- It("podman run add dns server", func() {
+ It("add dns server", func() {
session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("nameserver 1.2.3.4")))
})
- It("podman run add dns option", func() {
+ It("add dns option", func() {
session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("options debug")))
})
- It("podman run containers.conf remove all search domain", func() {
+ It("remove all search domain", func() {
session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("search"))))
})
- It("podman run use containers.conf search domain", func() {
+ It("add search domain", func() {
session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search")))
- Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
-
- Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
- Expect(session.OutputToString()).To(ContainSubstring("debug"))
+ Expect(session.Out.Contents()).To(
+ And(
+ ContainSubstring("foobar.com"),
+ ContainSubstring("1.2.3.4"),
+ ContainSubstring("debug"),
+ ))
})
- It("podman run containers.conf timezone", func() {
- //containers.conf timezone set to Pacific/Honolulu
+ It("add timezone", func() {
+ // containers.conf timezone set to Pacific/Honolulu
session := podmanTest.Podman([]string{"run", "--tz", "", ALPINE, "date", "+'%H %Z'"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -273,8 +290,8 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(ContainSubstring("EST"))
})
- It("podman run containers.conf umask", func() {
- //containers.conf umask set to 0002
+ It("add umask", func() {
+ // containers.conf umask set to 0002
if !strings.Contains(podmanTest.OCIRuntime, "crun") {
Skip("Test only works on crun")
}
@@ -285,16 +302,14 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(Equal("0002"))
})
- It("podman set network cmd options slirp options to allow host loopback", func() {
+ It("network slirp options to allow host loopback", func() {
session := podmanTest.Podman([]string{"run", "--network", "slirp4netns", ALPINE, "ping", "-c1", "10.0.2.2"})
session.Wait(30)
Expect(session).Should(Exit(0))
})
- It("podman-remote test localcontainers.conf versus remote containers.conf", func() {
- if !IsRemote() {
- Skip("this test is only for remote")
- }
+ It("podman-remote test localcontainers.conf", func() {
+ SkipIfNotRemote("this test is only for remote")
os.Setenv("CONTAINERS_CONF", "config/containers-remote.conf")
// Configuration that comes from remote server
@@ -309,34 +324,41 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search")))
- Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
- Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
- Expect(session.OutputToString()).To(ContainSubstring("debug"))
+ Expect(session.Out.Contents()).To(
+ And(
+ ContainSubstring("foobar.com"),
+ ContainSubstring("1.2.3.4"),
+ ContainSubstring("debug"),
+ ))
// sysctls
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/sys/net/ipv4/ping_group_range"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("1000"))
+ Expect(session.Out.Contents()).To(ContainSubstring("1000"))
// shm-size
session = podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("size=200k"))
+ Expect(session.Out.Contents()).To(ContainSubstring("size=200k"))
// ulimits
session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("500"))
+ Expect(session.Out.Contents()).To(ContainSubstring("500"))
// Configuration that comes from remote client
// Timezone
session = podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Or(ContainSubstring("EST"), ContainSubstring("EDT")))
+ Expect(session.Out.Contents()).To(
+ Or(
+ ContainSubstring("EST"),
+ ContainSubstring("EDT"),
+ ))
// Umask
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"})
@@ -345,48 +367,48 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(Equal("0022"))
})
- It("podman run containers.conf annotations test", func() {
- //containers.conf is set to "run.oci.keep_original_groups=1"
+ It("add annotations", func() {
+ // containers.conf is set to "run.oci.keep_original_groups=1"
session := podmanTest.Podman([]string{"create", "--rm", "--name", "test", fedoraMinimal})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .Config.Annotations }}", "test"})
inspect.WaitWithDefaultTimeout()
- Expect(inspect.OutputToString()).To(ContainSubstring("run.oci.keep_original_groups:1"))
+ Expect(inspect.Out.Contents()).To(ContainSubstring("run.oci.keep_original_groups:1"))
})
- It("podman run with --add-host and no-hosts=true fails", func() {
+ It("--add-host and no-hosts=true fails", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
- Expect(session.ErrorToString()).To(ContainSubstring("--no-hosts and --add-host cannot be set together"))
+ Expect(session.Err.Contents()).To(ContainSubstring("--no-hosts and --add-host cannot be set together"))
session = podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts=false", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})
- It("podman run with no-hosts=true /etc/hosts does not include hostname", func() {
+ It("no-hosts=true /etc/hosts does not include hostname", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--name", "test", ALPINE, "cat", "/etc/hosts"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Not(ContainSubstring("test")))
+ Expect(session.Out.Contents()).ToNot(ContainSubstring("test"))
session = podmanTest.Podman([]string{"run", "--rm", "--name", "test", "--no-hosts=false", ALPINE, "cat", "/etc/hosts"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("test"))
+ Expect(session.Out.Contents()).To(ContainSubstring("test"))
})
- It("podman info seccomp profile path", func() {
+ It("seccomp profile path", func() {
configPath := filepath.Join(podmanTest.TempDir, "containers.conf")
os.Setenv("CONTAINERS_CONF", configPath)
profile := filepath.Join(podmanTest.TempDir, "seccomp.json")
containersConf := []byte(fmt.Sprintf("[containers]\nseccomp_profile=\"%s\"", profile))
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
if IsRemote() {
podmanTest.RestartRemoteService()
@@ -398,7 +420,7 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(Equal(profile))
})
- It("podman info image_copy_tmp_dir", func() {
+ It("add image_copy_tmp_dir", func() {
session := podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -409,7 +431,7 @@ var _ = Describe("Podman run", func() {
containersConf := []byte("[engine]\nimage_copy_tmp_dir=\"/foobar\"")
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
if IsRemote() {
podmanTest.RestartRemoteService()
@@ -422,7 +444,7 @@ var _ = Describe("Podman run", func() {
containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage\"")
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
if IsRemote() {
podmanTest.RestartRemoteService()
}
@@ -430,11 +452,11 @@ var _ = Describe("Podman run", func() {
session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring("containers/storage/tmp"))
+ Expect(session.Out.Contents()).To(ContainSubstring("containers/storage/tmp"))
containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage1\"")
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
if IsRemote() {
podmanTest.RestartRemoteService()
}
@@ -442,18 +464,20 @@ var _ = Describe("Podman run", func() {
session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.ErrorToString()).To(ContainSubstring("invalid image_copy_tmp_dir"))
+ Expect(session.Err.Contents()).To(ContainSubstring("invalid image_copy_tmp_dir"))
})
- It("podman system service --help shows (default 20)", func() {
- SkipIfRemote("this test is only for local")
+ // FIXME not sure why this is here
+ It("system service --help shows (default 20)", func() {
+ SkipIfRemote("system service is not supported on clients")
+
result := podmanTest.Podman([]string{"system", "service", "--help"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("(default 1234)"))
+ Expect(result.Out.Contents()).To(ContainSubstring("(default 1234)"))
})
- It("podman bad infra_image name in containers.conf", func() {
+ It("bad infra_image name", func() {
infra1 := "i.do/not/exist:image"
infra2 := "i.still.do/not/exist:image"
errorString := "initializing source docker://" + infra1
@@ -463,7 +487,7 @@ var _ = Describe("Podman run", func() {
containersConf := []byte("[engine]\ninfra_image=\"" + infra1 + "\"")
err = ioutil.WriteFile(configPath, containersConf, os.ModePerm)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
if IsRemote() {
podmanTest.RestartRemoteService()
@@ -472,27 +496,52 @@ var _ = Describe("Podman run", func() {
result := podmanTest.Podman([]string{"pod", "create", "--infra-image", infra2})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
- Expect(result.ErrorToString()).To(ContainSubstring(error2String))
+ Expect(result.Err.Contents()).To(ContainSubstring(error2String))
result = podmanTest.Podman([]string{"pod", "create"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
- Expect(result.ErrorToString()).To(ContainSubstring(errorString))
+ Expect(result.Err.Contents()).To(ContainSubstring(errorString))
result = podmanTest.Podman([]string{"create", "--pod", "new:pod1", ALPINE})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
- Expect(result.ErrorToString()).To(ContainSubstring(errorString))
+ Expect(result.Err.Contents()).To(ContainSubstring(errorString))
+ })
+
+ It("set .engine.remote=true", func() {
+ SkipIfRemote("only meaningful when running ABI/local")
+
+ // Need to restore CONTAINERS_CONF or AfterEach() will fail
+ if path, found := os.LookupEnv("CONTAINERS_CONF"); found {
+ defer os.Setenv("CONTAINERS_CONF", path)
+ }
+
+ configPath := filepath.Join(podmanTest.TempDir, "containers-engine-remote.conf")
+ os.Setenv("CONTAINERS_CONF", configPath)
+ defer os.Remove(configPath)
+
+ err := ioutil.WriteFile(configPath, []byte("[engine]\nremote=true"), os.ModePerm)
+ Expect(err).ToNot(HaveOccurred())
+
+ // podmanTest.Podman() cannot be used as it was initialized remote==false
+ cmd := exec.Command(podmanTest.PodmanBinary, "info", "--format", "{{.Host.ServiceIsRemote}}")
+ session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
+ Expect(err).ToNot(HaveOccurred())
+
+ description := "Should have failed as there is no running remote API service available."
+ Eventually(session, DefaultWaitTimeout).Should(Exit(125), description)
+ Expect(session.Err).Should(Say("Error: unable to connect to Podman socket"))
})
It("podman containers.conf cgroups=disabled", func() {
if !strings.Contains(podmanTest.OCIRuntime, "crun") {
Skip("FIXME: requires crun")
}
- conffile := filepath.Join(podmanTest.TempDir, "container.conf")
+ conffile := filepath.Join(podmanTest.TempDir, "container.conf")
err := ioutil.WriteFile(conffile, []byte("[containers]\ncgroups=\"disabled\"\n"), 0755)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
result := podmanTest.Podman([]string{"create", ALPINE, "true"})
result.WaitWithDefaultTimeout()
@@ -500,7 +549,7 @@ var _ = Describe("Podman run", func() {
inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()})
inspect.WaitWithDefaultTimeout()
- Expect(inspect.OutputToString()).To(Not(Equal("disabled")))
+ Expect(inspect.OutputToString()).ToNot(Equal("disabled"))
os.Setenv("CONTAINERS_CONF", conffile)
if IsRemote() {
@@ -515,4 +564,16 @@ var _ = Describe("Podman run", func() {
Expect(inspect.OutputToString()).To(Equal("disabled"))
})
+ It("podman containers.conf runtime", func() {
+ SkipIfRemote("--runtime option is not available for remote commands")
+ conffile := filepath.Join(podmanTest.TempDir, "container.conf")
+ err := ioutil.WriteFile(conffile, []byte("[engine]\nruntime=\"testruntime\"\n"), 0755)
+ Expect(err).ToNot(HaveOccurred())
+
+ os.Setenv("CONTAINERS_CONF", conffile)
+ result := podmanTest.Podman([]string{"--help"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring("Path to the OCI-compatible binary used to run containers. (default \"testruntime\")"))
+ })
})
diff --git a/test/e2e/create_staticip_test.go b/test/e2e/create_staticip_test.go
index 5d234d717..4a1d926e0 100644
--- a/test/e2e/create_staticip_test.go
+++ b/test/e2e/create_staticip_test.go
@@ -106,6 +106,10 @@ var _ = Describe("Podman create with --ip flag", func() {
result = podmanTest.Podman([]string{"start", "test2"})
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
- Expect(result.ErrorToString()).To(ContainSubstring("requested IP address " + ip + " is not available"))
+ if podmanTest.NetworkBackend == CNI {
+ Expect(result.ErrorToString()).To(ContainSubstring("requested IP address " + ip + " is not available"))
+ } else if podmanTest.NetworkBackend == Netavark {
+ Expect(result.ErrorToString()).To(ContainSubstring("requested ip address %s is already allocated", ip))
+ }
})
})
diff --git a/test/e2e/create_staticmac_test.go b/test/e2e/create_staticmac_test.go
index c6694ff7f..5fd8e3bd6 100644
--- a/test/e2e/create_staticmac_test.go
+++ b/test/e2e/create_staticmac_test.go
@@ -52,7 +52,7 @@ var _ = Describe("Podman run with --mac-address flag", func() {
net := "n1" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
result := podmanTest.Podman([]string{"run", "--network", net, "--mac-address", "92:d0:c6:00:29:34", ALPINE, "ip", "addr"})
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index addf0ded0..6a4a394ef 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -598,7 +598,7 @@ var _ = Describe("Podman create", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
session = podmanTest.Podman([]string{"create", "--pod", name, "--network", netName, ALPINE, "top"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 976048886..55b9a8037 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -159,6 +159,50 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.OutputToString()).To(ContainSubstring("podman stop -t 5"))
})
+ It("podman generate systemd with user-defined dependencies", func() {
+ n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "--wants", "foobar.service", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Wants option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--after", "foobar.service", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined After option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--requires", "foobar.service", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Requires option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service"))
+
+ session = podmanTest.Podman([]string{
+ "generate", "systemd",
+ "--wants", "foobar.service", "--wants", "barfoo.service",
+ "--after", "foobar.service", "--after", "barfoo.service",
+ "--requires", "foobar.service", "--requires", "barfoo.service", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Want, After, Requires options
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service barfoo.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service barfoo.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service barfoo.service"))
+ })
+
It("podman generate systemd pod --name", func() {
n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
n.WaitWithDefaultTimeout()
@@ -213,6 +257,54 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.OutputToString()).To(ContainSubstring("/container-foo-1.service"))
})
+ It("podman generate systemd pod with user-defined dependencies", func() {
+ n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "--name", "--wants", "foobar.service", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Wants option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--name", "--after", "foobar.service", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined After option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--name", "--requires", "foobar.service", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Requires option
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service"))
+
+ session = podmanTest.Podman([]string{
+ "generate", "systemd", "--name",
+ "--wants", "foobar.service", "--wants", "barfoo.service",
+ "--after", "foobar.service", "--after", "barfoo.service",
+ "--requires", "foobar.service", "--requires", "barfoo.service", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // The generated systemd unit should contain the User-defined Want, After, Requires options
+ Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service barfoo.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service barfoo.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service barfoo.service"))
+ })
+
It("podman generate systemd --new --name foo", func() {
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
n.WaitWithDefaultTimeout()
diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go
index 37381a561..b4a59c54d 100644
--- a/test/e2e/libpod_suite_remote_test.go
+++ b/test/e2e/libpod_suite_remote_test.go
@@ -153,8 +153,9 @@ func (p *PodmanTestIntegration) StopRemoteService() {
// MakeOptions assembles all the podman main options
func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
- podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s",
- p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
+ networkDir := p.NetworkConfigDir
+ podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --cgroup-manager %s",
+ p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.CgroupManager), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go
index 3d0f44dc1..1280b3e83 100644
--- a/test/e2e/login_logout_test.go
+++ b/test/e2e/login_logout_test.go
@@ -11,7 +11,6 @@ import (
. "github.com/containers/podman/v4/test/utils"
. "github.com/onsi/ginkgo"
- "github.com/onsi/ginkgo/config"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
)
@@ -24,7 +23,6 @@ var _ = Describe("Podman login and logout", func() {
authPath string
certPath string
certDirPath string
- port int
server string
testImg string
registriesConfWithSearch []byte
@@ -62,7 +60,7 @@ var _ = Describe("Podman login and logout", func() {
f.WriteString(session.OutputToString())
f.Sync()
- port = 4999 + config.GinkgoConfig.ParallelNode
+ port := GetPort()
server = strings.Join([]string{"localhost", strconv.Itoa(port)}, ":")
registriesConfWithSearch = []byte(fmt.Sprintf("[registries.search]\nregistries = ['%s']", server))
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index 82b9dcd09..baef142ba 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -45,7 +45,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
dis := podmanTest.Podman([]string{"network", "disconnect", netName, "foobar"})
dis.WaitWithDefaultTimeout()
@@ -57,12 +57,12 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
session = podmanTest.Podman([]string{"create", "--name", "test", "--network", "slirp4netns", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
con := podmanTest.Podman([]string{"network", "disconnect", netName, "test"})
con.WaitWithDefaultTimeout()
@@ -75,7 +75,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
@@ -111,7 +111,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
dis := podmanTest.Podman([]string{"network", "connect", netName, "foobar"})
dis.WaitWithDefaultTimeout()
@@ -123,12 +123,12 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
session = podmanTest.Podman([]string{"create", "--name", "test", "--network", "slirp4netns", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
con := podmanTest.Podman([]string{"network", "connect", netName, "test"})
con.WaitWithDefaultTimeout()
@@ -141,7 +141,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
@@ -164,7 +164,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
@@ -180,7 +180,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session = podmanTest.Podman([]string{"network", "create", newNetName, "--subnet", "10.11.100.0/24"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(newNetName)
+ defer podmanTest.removeNetwork(newNetName)
ip := "10.11.100.99"
mac := "44:11:44:11:44:11"
@@ -218,13 +218,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
netName2 := "connect2" + stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", netName2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName1, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
@@ -257,7 +257,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + netName})
session.WaitWithDefaultTimeout()
@@ -277,7 +277,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session = podmanTest.Podman([]string{"network", "create", newNetName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(newNetName)
+ defer podmanTest.removeNetwork(newNetName)
session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + newNetName})
session.WaitWithDefaultTimeout()
@@ -304,13 +304,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
netName2 := "aliasTest" + stringid.GenerateNonCryptoID()
session2 := podmanTest.Podman([]string{"network", "create", netName2})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName1 + "," + netName2, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
@@ -349,7 +349,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + netName})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index ade78a308..7589adaab 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -45,7 +45,7 @@ var _ = Describe("Podman network create", func() {
netName := "subnet-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
@@ -88,7 +88,7 @@ var _ = Describe("Podman network create", func() {
netName := "ipv6-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
@@ -127,7 +127,7 @@ var _ = Describe("Podman network create", func() {
netName := "dual-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2::/64", "--ipv6", netName})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
@@ -160,7 +160,7 @@ var _ = Describe("Podman network create", func() {
netName2 := "dual-" + stringid.GenerateNonCryptoID()
nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:10:3:2::/64", "--ipv6", netName2})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
@@ -215,7 +215,7 @@ var _ = Describe("Podman network create", func() {
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ipv6", name})
nc.WaitWithDefaultTimeout()
Expect(nc).To(Exit(0))
- defer podmanTest.removeCNINetwork(name)
+ defer podmanTest.removeNetwork(name)
nc = podmanTest.Podman([]string{"network", "inspect", name})
nc.WaitWithDefaultTimeout()
@@ -229,7 +229,7 @@ var _ = Describe("Podman network create", func() {
nc := podmanTest.Podman([]string{"network", "create", "--ipv6", name})
nc.WaitWithDefaultTimeout()
Expect(nc).To(Exit(0))
- defer podmanTest.removeCNINetwork(name)
+ defer podmanTest.removeNetwork(name)
nc = podmanTest.Podman([]string{"network", "inspect", name})
nc.WaitWithDefaultTimeout()
@@ -254,7 +254,7 @@ var _ = Describe("Podman network create", func() {
netName := "same-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", netName})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
ncFail := podmanTest.Podman([]string{"network", "create", netName})
@@ -266,13 +266,13 @@ var _ = Describe("Podman network create", func() {
netName1 := "sub1-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName1})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
Expect(nc).Should(Exit(0))
netName2 := "sub2-" + stringid.GenerateNonCryptoID()
ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName2})
ncFail.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(ncFail).To(ExitWithError())
})
@@ -280,13 +280,13 @@ var _ = Describe("Podman network create", func() {
netName1 := "subipv61-" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName1})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
Expect(nc).Should(Exit(0))
netName2 := "subipv62-" + stringid.GenerateNonCryptoID()
ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName2})
ncFail.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(ncFail).To(ExitWithError())
})
@@ -300,7 +300,7 @@ var _ = Describe("Podman network create", func() {
net := "mtu-test" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "mtu=9000", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
nc = podmanTest.Podman([]string{"network", "inspect", net})
@@ -313,7 +313,7 @@ var _ = Describe("Podman network create", func() {
net := "vlan-test" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "vlan=9", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
nc = podmanTest.Podman([]string{"network", "inspect", net})
@@ -326,15 +326,16 @@ var _ = Describe("Podman network create", func() {
net := "invalid-test" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "foo=bar", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).To(ExitWithError())
})
It("podman network create with internal should not have dnsname", func() {
+ SkipUntilAardvark(podmanTest)
net := "internal-test" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--internal", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
// Not performing this check on remote tests because it is a logrus error which does
// not come back via stderr on the remote client.
@@ -356,4 +357,82 @@ var _ = Describe("Podman network create", func() {
}
})
+ It("podman network create with multiple subnets", func() {
+ name := "subnets-" + stringid.GenerateNonCryptoID()
+ subnet1 := "10.10.0.0/24"
+ subnet2 := "10.10.1.0/24"
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name})
+ nc.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(name)
+ Expect(nc).To(Exit(0))
+ Expect(nc.OutputToString()).To(Equal(name))
+
+ inspect := podmanTest.Podman([]string{"network", "inspect", name})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).To(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": false`))
+ })
+
+ It("podman network create with multiple subnets dual stack", func() {
+ name := "subnets-" + stringid.GenerateNonCryptoID()
+ subnet1 := "10.10.2.0/24"
+ subnet2 := "fd52:2a5a:747e:3acd::/64"
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name})
+ nc.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(name)
+ Expect(nc).To(Exit(0))
+ Expect(nc.OutputToString()).To(Equal(name))
+
+ inspect := podmanTest.Podman([]string{"network", "inspect", name})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).To(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`))
+ })
+
+ It("podman network create with multiple subnets dual stack with gateway and range", func() {
+ name := "subnets-" + stringid.GenerateNonCryptoID()
+ subnet1 := "10.10.3.0/24"
+ gw1 := "10.10.3.10"
+ range1 := "10.10.3.0/26"
+ subnet2 := "fd52:2a5a:747e:3acd::/64"
+ gw2 := "fd52:2a5a:747e:3acd::10"
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--ip-range", range1, "--subnet", subnet2, "--gateway", gw2, name})
+ nc.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(name)
+ Expect(nc).To(Exit(0))
+ Expect(nc.OutputToString()).To(Equal(name))
+
+ inspect := podmanTest.Podman([]string{"network", "inspect", name})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).To(Exit(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw1))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"start_ip": "10.10.3.1",`))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"end_ip": "10.10.3.63"`))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw2))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`))
+ })
+
+ It("podman network create invalid options with multiple subnets", func() {
+ name := "subnets-" + stringid.GenerateNonCryptoID()
+ subnet1 := "10.10.3.0/24"
+ gw1 := "10.10.3.10"
+ gw2 := "fd52:2a5a:747e:3acd::10"
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--gateway", gw2, name})
+ nc.WaitWithDefaultTimeout()
+ Expect(nc).To(Exit(125))
+ Expect(nc.ErrorToString()).To(Equal("Error: cannot set more gateways than subnets"))
+
+ range1 := "10.10.3.0/26"
+ range2 := "10.10.3.0/28"
+ nc = podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--ip-range", range1, "--ip-range", range2, name})
+ nc.WaitWithDefaultTimeout()
+ Expect(nc).To(Exit(125))
+ Expect(nc.ErrorToString()).To(Equal("Error: cannot set more ranges than subnets"))
+ })
})
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 877ad37b8..bd30a1f5d 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -38,6 +38,26 @@ var _ = Describe("Podman network", func() {
})
+ It("podman --cni-config-dir backwards compat", func() {
+ SkipIfRemote("--cni-config-dir only works locally")
+ netDir, err := CreateTempDirInTempDir()
+ Expect(err).ToNot(HaveOccurred())
+ defer os.RemoveAll(netDir)
+ session := podmanTest.Podman([]string{"--cni-config-dir", netDir, "network", "ls", "--noheading"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ // default network always exists
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
+
+ // check that the only file in the directory is the network lockfile
+ dir, err := os.Open(netDir)
+ Expect(err).ToNot(HaveOccurred())
+ names, err := dir.Readdirnames(5)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(names).To(HaveLen(1))
+ Expect(names[0]).To(Or(Equal("netavark.lock"), Equal("cni.lock")))
+ })
+
It("podman network list", func() {
name, path := generateNetworkConfig(podmanTest)
defer removeConf(path)
@@ -98,13 +118,13 @@ var _ = Describe("Podman network", func() {
label2 := "abcdef"
session := podmanTest.Podman([]string{"network", "create", "--label", label1, net1})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
Expect(session).Should(Exit(0))
net2 := "labelnet" + stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", "--label", label1, "--label", label2, net2})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net2)
+ defer podmanTest.removeNetwork(net2)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"network", "ls", "--filter", "label=" + label1})
@@ -124,7 +144,7 @@ var _ = Describe("Podman network", func() {
net := "net" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"network", "ls", "--filter", "namr=ab"})
@@ -149,9 +169,16 @@ var _ = Describe("Podman network", func() {
netID := "6073aefe03cdf8f29be5b23ea9795c431868a3a22066a6290b187691614fee84"
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
+ if podmanTest.NetworkBackend == Netavark {
+ // netavark uses a different algo for determining the id and it is not repeatable
+ getid := podmanTest.Podman([]string{"network", "inspect", net, "--format", "{{.ID}}"})
+ getid.WaitWithDefaultTimeout()
+ Expect(getid).Should(Exit(0))
+ netID = getid.OutputToString()
+ }
// Tests Default Table Output
session = podmanTest.Podman([]string{"network", "ls", "--filter", "id=" + netID})
session.WaitWithDefaultTimeout()
@@ -250,7 +277,7 @@ var _ = Describe("Podman network", func() {
netName := "net-" + stringid.GenerateNonCryptoID()
network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName})
network.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(network).Should(Exit(0))
ctrName := "testCtr"
@@ -280,13 +307,13 @@ var _ = Describe("Podman network", func() {
netName1 := "net1-" + stringid.GenerateNonCryptoID()
network1 := podmanTest.Podman([]string{"network", "create", netName1})
network1.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
Expect(network1).Should(Exit(0))
netName2 := "net2-" + stringid.GenerateNonCryptoID()
network2 := podmanTest.Podman([]string{"network", "create", netName2})
network2.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(network2).Should(Exit(0))
ctrName := "testCtr"
@@ -317,13 +344,13 @@ var _ = Describe("Podman network", func() {
netName1 := "net1-" + stringid.GenerateNonCryptoID()
network1 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.0/25", netName1})
network1.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
Expect(network1).Should(Exit(0))
netName2 := "net2-" + stringid.GenerateNonCryptoID()
network2 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.128/26", netName2})
network2.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(network2).Should(Exit(0))
ctrName := "testCtr"
@@ -360,7 +387,7 @@ var _ = Describe("Podman network", func() {
session := podmanTest.Podman([]string{"network", "create", network})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(network)
+ defer podmanTest.removeNetwork(network)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"run", "--name", container, "--network", network, "-d", ALPINE, "top"})
@@ -386,7 +413,7 @@ var _ = Describe("Podman network", func() {
netName := "net-" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"pod", "create", "--network", netName})
@@ -422,13 +449,13 @@ var _ = Describe("Podman network", func() {
netName1 := "net1-" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName1)
+ defer podmanTest.removeNetwork(netName1)
Expect(session).Should(Exit(0))
netName2 := "net2-" + stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", netName2})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName2)
+ defer podmanTest.removeNetwork(netName2)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"network", "rm", netName1, netName2})
@@ -440,11 +467,12 @@ var _ = Describe("Podman network", func() {
})
It("podman network with multiple aliases", func() {
+ SkipUntilAardvark(podmanTest)
var worked bool
netName := "aliasTest" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(session).Should(Exit(0))
interval := time.Duration(250 * time.Millisecond)
@@ -490,10 +518,12 @@ var _ = Describe("Podman network", func() {
})
It("podman network create/remove macvlan", func() {
+ // Netavark currently does not do dhcp so the this test fails
+ SkipIfNetavark(podmanTest)
net := "macvlan" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "--macvlan", "lo", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
nc = podmanTest.Podman([]string{"network", "rm", net})
@@ -502,10 +532,12 @@ var _ = Describe("Podman network", func() {
})
It("podman network create/remove macvlan as driver (-d) no device name", func() {
+ // Netavark currently does not do dhcp so the this test fails
+ SkipIfNetavark(podmanTest)
net := "macvlan" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
inspect := podmanTest.Podman([]string{"network", "inspect", net})
@@ -527,10 +559,12 @@ var _ = Describe("Podman network", func() {
})
It("podman network create/remove macvlan as driver (-d) with device name", func() {
+ // Netavark currently does not do dhcp so the this test fails
+ SkipIfNetavark(podmanTest)
net := "macvlan" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
inspect := podmanTest.Podman([]string{"network", "inspect", net})
@@ -557,7 +591,7 @@ var _ = Describe("Podman network", func() {
net := "net" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"network", "exists", net})
@@ -573,7 +607,7 @@ var _ = Describe("Podman network", func() {
net := "macvlan" + stringid.GenerateNonCryptoID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", "-o", "mtu=1500", "--gateway", "192.168.1.254", "--subnet", "192.168.1.0/24", net})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(nc).Should(Exit(0))
inspect := podmanTest.Podman([]string{"network", "inspect", net})
@@ -602,7 +636,7 @@ var _ = Describe("Podman network", func() {
It("podman network prune --filter", func() {
// set custom cni directory to prevent flakes
- podmanTest.CNIConfigDir = tempdir
+ podmanTest.NetworkConfigDir = tempdir
if IsRemote() {
podmanTest.RestartRemoteService()
}
@@ -610,7 +644,7 @@ var _ = Describe("Podman network", func() {
nc := podmanTest.Podman([]string{"network", "create", net1})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
Expect(nc).Should(Exit(0))
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
@@ -650,7 +684,7 @@ var _ = Describe("Podman network", func() {
It("podman network prune", func() {
// set custom cni directory to prevent flakes
- podmanTest.CNIConfigDir = tempdir
+ podmanTest.NetworkConfigDir = tempdir
if IsRemote() {
podmanTest.RestartRemoteService()
}
@@ -664,12 +698,12 @@ var _ = Describe("Podman network", func() {
net2 := net + "2"
nc := podmanTest.Podman([]string{"network", "create", net1})
nc.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
Expect(nc).Should(Exit(0))
nc2 := podmanTest.Podman([]string{"network", "create", net2})
nc2.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net2)
+ defer podmanTest.removeNetwork(net2)
Expect(nc2).Should(Exit(0))
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go
index bbebf7949..70e042b4d 100644
--- a/test/e2e/play_build_test.go
+++ b/test/e2e/play_build_test.go
@@ -173,7 +173,7 @@ LABEL marge=mom
err = writeYaml(testYAML, filepath.Join(yamlDir, "top.yaml"))
Expect(err).To(BeNil())
- // build an image called foobar but make sure it doesnt have
+ // build an image called foobar but make sure it doesn't have
// the same label as the yaml buildfile, so we can check that
// the image is NOT rebuilt.
err = writeYaml(prebuiltImage, filepath.Join(yamlDir, "Containerfile"))
@@ -220,7 +220,7 @@ LABEL marge=mom
err = writeYaml(testYAML, filepath.Join(yamlDir, "top.yaml"))
Expect(err).To(BeNil())
- // build an image called foobar but make sure it doesnt have
+ // build an image called foobar but make sure it doesn't have
// the same label as the yaml buildfile, so we can check that
// the image is NOT rebuilt.
err = writeYaml(prebuiltImage, filepath.Join(yamlDir, "Containerfile"))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 63c9bf7f3..c0c71652e 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -78,6 +78,25 @@ spec:
- 24h
status: {}
`
+
+var podWithoutConfigMapDefined = `
+apiVersion: v1
+kind: Pod
+metadata:
+ name: testpod1
+spec:
+ containers:
+ - name: alpine
+ image: quay.io/libpod/alpine:latest
+ volumeMounts:
+ - name: mycm
+ mountPath: /mycm
+ volumes:
+ - name: mycm
+ configMap:
+ name: mycm
+`
+
var sharedNamespacePodYaml = `
apiVersion: v1
kind: Pod
@@ -1235,6 +1254,16 @@ var _ = Describe("Podman play kube", func() {
}
})
+ It("podman play kube with non-existing configmap", func() {
+ err := writeYaml(podWithoutConfigMapDefined, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(125))
+ Expect(kube.ErrorToString()).To(ContainSubstring("failed to create volume \"mycm\": no such ConfigMap \"mycm\""))
+ })
+
It("podman play kube test HostAliases with --no-hosts", func() {
pod := getPod(withHostAliases("192.168.1.2", []string{
"test1.podman.io",
@@ -2161,7 +2190,7 @@ spec:
net := "playkube" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
ips := []string{"10.25.31.5", "10.25.31.10", "10.25.31.15"}
@@ -2205,12 +2234,12 @@ spec:
net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1})
net.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
Expect(net).Should(Exit(0))
net = podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.12.0/24", net2})
net.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net2)
+ defer podmanTest.removeNetwork(net2)
Expect(net).Should(Exit(0))
ip1 := "10.0.11.5"
@@ -2955,7 +2984,7 @@ invalid kube kind
inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
- Expect(inspect.OutputToString()).To(ContainSubstring(`map[]`))
+ Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue))
})
It("podman play kube teardown", func() {
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index cd7f72ac0..04e8cfd07 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -109,7 +109,8 @@ var _ = Describe("Podman pod create", func() {
It("podman create pod with network portbindings", func() {
name := "test"
- session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8081:80"})
+ port := GetPort()
+ session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", fmt.Sprintf("%d:80", port)})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
pod := session.OutputToString()
@@ -117,24 +118,21 @@ var _ = Describe("Podman pod create", func() {
webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", nginx})
webserver.WaitWithDefaultTimeout()
Expect(webserver).Should(Exit(0))
-
- check := SystemExec("nc", []string{"-z", "localhost", "8081"})
- Expect(check).Should(Exit(0))
+ Expect(ncz(port)).To(BeTrue())
})
It("podman create pod with id file with network portbindings", func() {
file := filepath.Join(podmanTest.TempDir, "pod.id")
name := "test"
- session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8082:80"})
+ port := GetPort()
+ session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", fmt.Sprintf("%d:80", port)})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
webserver := podmanTest.Podman([]string{"run", "--pod-id-file", file, "-dt", nginx})
webserver.WaitWithDefaultTimeout()
Expect(webserver).Should(Exit(0))
-
- check := SystemExec("nc", []string{"-z", "localhost", "8082"})
- Expect(check).Should(Exit(0))
+ Expect(ncz(port)).To(BeTrue())
})
It("podman create pod with no infra but portbindings should fail", func() {
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 29ee73d35..a0a1e1438 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -299,7 +299,7 @@ var _ = Describe("Podman ps", func() {
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
session = podmanTest.Podman([]string{"pod", "create", "--network", net})
session.WaitWithDefaultTimeout()
@@ -338,12 +338,12 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"network", "create", net1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
net2 := stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", net2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net2)
+ defer podmanTest.removeNetwork(net2)
session = podmanTest.Podman([]string{"pod", "create", "--network", net1 + "," + net2})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 0c93c430b..021ebc30b 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -822,7 +822,7 @@ var _ = Describe("Podman ps", func() {
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
session = podmanTest.Podman([]string{"create", "--network", net, ALPINE})
session.WaitWithDefaultTimeout()
@@ -865,12 +865,12 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"network", "create", net1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net1)
+ defer podmanTest.removeNetwork(net1)
net2 := stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", net2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- defer podmanTest.removeCNINetwork(net2)
+ defer podmanTest.removeNetwork(net2)
session = podmanTest.Podman([]string{"create", "--network", net1 + "," + net2, ALPINE})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 87b1f143e..4c056df10 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -78,9 +78,9 @@ var _ = Describe("Podman run networking", func() {
It("podman run network expose port 222", func() {
SkipIfRootless("iptables is not supported for rootless users")
session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"})
- session.Wait(30)
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- results := SystemExec("iptables", []string{"-t", "nat", "-L"})
+ results := SystemExec("iptables", []string{"-t", "nat", "-nvL"})
Expect(results).Should(Exit(0))
Expect(results.OutputToString()).To(ContainSubstring("222"))
Expect(results.OutputToString()).To(ContainSubstring("223"))
@@ -371,31 +371,35 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run network expose host port 80 to container port 8000", func() {
+ It("podman run network expose host port 80 to container port", func() {
SkipIfRootless("iptables is not supported for rootless users")
- session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"})
- session.Wait(30)
+ port1 := GetPort()
+ port2 := GetPort()
+ session := podmanTest.Podman([]string{"run", "-dt", "-p", fmt.Sprintf("%d:%d", port1, port2), ALPINE, "/bin/sh"})
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
results := SystemExec("iptables", []string{"-t", "nat", "-L"})
Expect(results).Should(Exit(0))
- Expect(results.OutputToString()).To(ContainSubstring("8000"))
+ Expect(results.OutputToString()).To(ContainSubstring(fmt.Sprintf("%d", port2)))
- ncBusy := SystemExec("nc", []string{"-l", "-p", "80"})
+ ncBusy := SystemExec("nc", []string{"-l", "-p", fmt.Sprintf("%d", port1)})
Expect(ncBusy).To(ExitWithError())
})
It("podman run network expose host port 18081 to container port 8000 using rootlesskit port handler", func() {
- session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", "18081:8000", ALPINE, "/bin/sh"})
- session.Wait(30)
+ port1 := GetPort()
+ port2 := GetPort()
+ session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", fmt.Sprintf("%d:%d", port2, port1), ALPINE, "/bin/sh"})
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- ncBusy := SystemExec("nc", []string{"-l", "-p", "18081"})
+ ncBusy := SystemExec("nc", []string{"-l", "-p", fmt.Sprintf("%d", port2)})
Expect(ncBusy).To(ExitWithError())
})
It("podman run slirp4netns verify net.ipv6.conf.default.accept_dad=0", func() {
session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "ip", "addr"})
- session.Wait(30)
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// check the ipv6 setup id done without delay (https://github.com/containers/podman/issues/11062)
Expect(session.OutputToString()).To(ContainSubstring("inet6 fd00::"))
@@ -403,12 +407,12 @@ EXPOSE 2004-2005/tcp`, ALPINE)
const ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/all/accept_dad"
cat := SystemExec("cat", []string{ipv6ConfDefaultAcceptDadSysctl})
- cat.Wait(30)
+ cat.WaitWithDefaultTimeout()
Expect(cat).Should(Exit(0))
sysctlValue := cat.OutputToString()
session = podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "cat", ipv6ConfDefaultAcceptDadSysctl})
- session.Wait(30)
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(Equal(sysctlValue))
})
@@ -460,19 +464,20 @@ EXPOSE 2004-2005/tcp`, ALPINE)
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
Expect(slirp4netnsHelp).Should(Exit(0))
networkConfiguration := "slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true"
+ port := GetPort()
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
- ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8083"})
- session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
- session.Wait(30)
- ncListener.Wait(30)
+ ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", fmt.Sprintf("%d", port)})
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)})
+ session.WaitWithDefaultTimeout()
+ ncListener.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(ncListener).Should(Exit(0))
Expect(ncListener.ErrorToString()).To(ContainSubstring("127.0.0.1"))
} else {
- session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
- session.Wait(30)
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)})
+ session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
}
@@ -481,14 +486,15 @@ EXPOSE 2004-2005/tcp`, ALPINE)
It("podman run network bind to HostIP", func() {
ip, err := utils.HostIP()
Expect(err).To(BeNil())
+ port := GetPort()
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
Expect(slirp4netnsHelp).Should(Exit(0))
networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip.String())
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
- ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8084"})
- session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
+ ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", fmt.Sprintf("%d", port)})
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)})
session.Wait(30)
ncListener.Wait(30)
@@ -496,7 +502,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(ncListener).Should(Exit(0))
Expect(ncListener.ErrorToString()).To(ContainSubstring(ip.String()))
} else {
- session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
+ session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)})
session.Wait(30)
Expect(session).To(ExitWithError())
Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
@@ -505,10 +511,10 @@ EXPOSE 2004-2005/tcp`, ALPINE)
It("podman run network expose ports in image metadata", func() {
session := podmanTest.Podman([]string{"create", "--name", "test", "-t", "-P", nginx})
- session.Wait(90)
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
results := podmanTest.Podman([]string{"inspect", "test"})
- results.Wait(30)
+ results.WaitWithDefaultTimeout()
Expect(results).Should(Exit(0))
Expect(results.OutputToString()).To(ContainSubstring(`"80/tcp":`))
})
@@ -533,7 +539,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
It("podman run forward sctp protocol", func() {
SkipIfRootless("sctp protocol only works as root")
session := podmanTest.Podman([]string{"--log-level=info", "run", "--name=test", "-p", "80/sctp", "-p", "81/sctp", ALPINE})
- session.Wait(90)
+ session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// we can only check logrus on local podman
if !IsRemote() {
@@ -541,7 +547,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(strings.Count(session.ErrorToString(), "Port reservation for SCTP is not supported")).To(Equal(1), "`Port reservation for SCTP is not supported` is not displayed exactly one time in the logrus logs")
}
results := podmanTest.Podman([]string{"inspect", "test"})
- results.Wait(30)
+ results.WaitWithDefaultTimeout()
Expect(results).Should(Exit(0))
Expect(results.OutputToString()).To(ContainSubstring(`"80/sctp":`))
Expect(results.OutputToString()).To(ContainSubstring(`"81/sctp":`))
@@ -701,7 +707,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"})
run.WaitWithDefaultTimeout()
@@ -710,11 +716,12 @@ EXPOSE 2004-2005/tcp`, ALPINE)
})
It("podman cni network works across user ns", func() {
+ SkipUntilAardvark(podmanTest)
netName := stringid.GenerateNonCryptoID()
create := podmanTest.Podman([]string{"network", "create", netName})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
name := "nc-server"
run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "9480"})
@@ -740,7 +747,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.40.0/24", netName})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--pod", "new:" + podname, "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"})
run.WaitWithDefaultTimeout()
@@ -808,6 +815,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
})
It("podman run check dnsname plugin", func() {
+ SkipUntilAardvark(podmanTest)
pod := "testpod"
session := podmanTest.Podman([]string{"pod", "create", "--name", pod})
session.WaitWithDefaultTimeout()
@@ -816,7 +824,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
net := "IntTest" + stringid.GenerateNonCryptoID()
session = podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
pod2 := "testpod2"
@@ -843,10 +851,11 @@ EXPOSE 2004-2005/tcp`, ALPINE)
})
It("podman run check dnsname adds dns search domain", func() {
+ SkipUntilAardvark(podmanTest)
net := "dnsname" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(net)
+ defer podmanTest.removeNetwork(net)
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"run", "--network", net, ALPINE, "cat", "/etc/resolv.conf"})
@@ -867,4 +876,17 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(inspectOut[0].NetworkSettings.Networks).To(HaveLen(1))
Expect(inspectOut[0].NetworkSettings.Networks).To(HaveKey("podman"))
})
+
+ // see https://github.com/containers/podman/issues/12972
+ It("podman run check network-alias works on networks without dns", func() {
+ net := "dns" + stringid.GenerateNonCryptoID()
+ session := podmanTest.Podman([]string{"network", "create", "--disable-dns", net})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(net)
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--network", net, "--network-alias", "abcdef", ALPINE, "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
})
diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go
index cf014d46e..b78a37495 100644
--- a/test/e2e/run_staticip_test.go
+++ b/test/e2e/run_staticip_test.go
@@ -71,7 +71,7 @@ var _ = Describe("Podman run with --ip flag", func() {
ipv6 := "fd46:db93:aa76:ac37::10"
net := podmanTest.Podman([]string{"network", "create", "--subnet", "fd46:db93:aa76:ac37::/64", netName})
net.WaitWithDefaultTimeout()
- defer podmanTest.removeCNINetwork(netName)
+ defer podmanTest.removeNetwork(netName)
Expect(net).To(Exit(0))
result := podmanTest.Podman([]string{"run", "-ti", "--network", netName, "--ip6", ipv6, ALPINE, "ip", "addr"})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 62a454e29..91a2eddad 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1926,4 +1926,14 @@ WORKDIR /madethis`, BB)
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("i686"))
})
+
+ It("podman run /dev/shm has nosuid,noexec,nodev", func() {
+ session := podmanTest.Podman([]string{"run", ALPINE, "grep", "/dev/shm", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ output := session.OutputToString()
+ Expect(output).To(ContainSubstring("nosuid"))
+ Expect(output).To(ContainSubstring("noexec"))
+ Expect(output).To(ContainSubstring("nodev"))
+ })
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 00faf8089..d23c5dc14 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -260,6 +260,60 @@ var _ = Describe("Podman run with volumes", func() {
})
+ It("podman support overlay on named volume with custom upperdir and workdir", func() {
+ SkipIfRemote("Overlay volumes only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+
+ // create persistent upperdir on host
+ upperDir := filepath.Join(tempdir, "upper")
+ err := os.Mkdir(upperDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+upperDir)
+
+ // create persistent workdir on host
+ workDir := filepath.Join(tempdir, "work")
+ err = os.Mkdir(workDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+workDir)
+
+ overlayOpts := fmt.Sprintf("upperdir=%s,workdir=%s", upperDir, workDir)
+
+ session := podmanTest.Podman([]string{"volume", "create", "myvolume"})
+ session.WaitWithDefaultTimeout()
+ volName := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ // create file on actual volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "echo hello >> " + "/data/test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // create file on overlay volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must contain `overlay` file since it should be persistent on specified upper and workdir
+ Expect(session.OutputToString()).To(ContainSubstring("overlay"))
+ // this should be there since `test` was written on actual volume not on any overlay
+ Expect(session.OutputToString()).To(ContainSubstring("test"))
+
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must not contain `overlay` file which was on custom upper and workdir since we have not specified any upper or workdir
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlay")))
+ // this should be there since `test` was written on actual volume not on any overlay
+ Expect(session.OutputToString()).To(ContainSubstring("test"))
+
+ })
+
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index f8d6019b0..07198d799 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -32,18 +32,6 @@ var _ = Describe("Podman search", func() {
podmanTest *PodmanTestIntegration
)
- var registryEndpoints = []endpoint{
- {"localhost", "5001"},
- {"localhost", "5002"},
- {"localhost", "5003"},
- {"localhost", "5004"},
- {"localhost", "5005"},
- {"localhost", "5006"},
- {"localhost", "5007"},
- {"localhost", "5008"},
- {"localhost", "5009"},
- }
-
const regFileContents = `
[registries.search]
registries = ['{{.Host}}:{{.Port}}']
@@ -217,21 +205,19 @@ registries = ['{{.Host}}:{{.Port}}']`
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
- lock := GetPortLock(registryEndpoints[0].Port)
- defer lock.Unlock()
-
+ port := GetPort()
fakereg := podmanTest.Podman([]string{"run", "-d", "--name", "registry",
- "-p", fmt.Sprintf("%s:5000", registryEndpoints[0].Port),
+ "-p", fmt.Sprintf("%d:5000", port),
registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
fakereg.WaitWithDefaultTimeout()
Expect(fakereg).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port)
}
-
+ ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"}
search := podmanTest.Podman([]string{"search",
- fmt.Sprintf("%s/fake/image:andtag", registryEndpoints[0].Address()), "--tls-verify=false"})
+ fmt.Sprintf("%s/fake/image:andtag", ep.Address()), "--tls-verify=false"})
search.WaitWithDefaultTimeout()
// if this test succeeded, there will be no output (there is no entry named fake/image:andtag in an empty registry)
@@ -245,20 +231,19 @@ registries = ['{{.Host}}:{{.Port}}']`
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
- lock := GetPortLock(registryEndpoints[3].Port)
- defer lock.Unlock()
+ port := GetPort()
registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry3",
- "-p", fmt.Sprintf("%s:5000", registryEndpoints[3].Port), registry,
+ "-p", fmt.Sprintf("%d:5000", port), registry,
"/entrypoint.sh", "/etc/docker/registry/config.yml"})
registry.WaitWithDefaultTimeout()
Expect(registry).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry3", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port)
}
-
+ ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"}
podmanTest.RestoreArtifact(ALPINE)
- image := fmt.Sprintf("%s/my-alpine", registryEndpoints[3].Address())
+ image := fmt.Sprintf("%s/my-alpine", ep.Address())
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
@@ -269,7 +254,7 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search.OutputToString()).ShouldNot(BeEmpty())
// podman search v2 registry with empty query
- searchEmpty := podmanTest.Podman([]string{"search", fmt.Sprintf("%s/", registryEndpoints[3].Address()), "--tls-verify=false"})
+ searchEmpty := podmanTest.Podman([]string{"search", fmt.Sprintf("%s/", ep.Address()), "--tls-verify=false"})
searchEmpty.WaitWithDefaultTimeout()
Expect(searchEmpty).Should(Exit(0))
Expect(len(searchEmpty.OutputToStringArray())).To(BeNumerically(">=", 1))
@@ -281,26 +266,26 @@ registries = ['{{.Host}}:{{.Port}}']`
Skip("No registry image for ppc64le")
}
- lock := GetPortLock(registryEndpoints[4].Port)
- defer lock.Unlock()
- registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[4].Port),
+ port := GetPort()
+ ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"}
+ registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port),
"--name", "registry4", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
registry.WaitWithDefaultTimeout()
Expect(registry).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry4", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("unable to start registry on port %s", port)
}
podmanTest.RestoreArtifact(ALPINE)
- image := fmt.Sprintf("%s/my-alpine", registryEndpoints[4].Address())
+ image := fmt.Sprintf("%s/my-alpine", ep.Address())
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
// registries.conf set up
var buffer bytes.Buffer
- registryFileTmpl.Execute(&buffer, registryEndpoints[4])
+ registryFileTmpl.Execute(&buffer, ep)
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry4.conf", tempdir), buffer.Bytes(), 0644)
if IsRemote() {
@@ -323,25 +308,25 @@ registries = ['{{.Host}}:{{.Port}}']`
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
- lock := GetPortLock(registryEndpoints[5].Port)
- defer lock.Unlock()
- registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[5].Port),
+ port := GetPort()
+ ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"}
+ registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port),
"--name", "registry5", registry})
registry.WaitWithDefaultTimeout()
Expect(registry).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry5", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port)
}
podmanTest.RestoreArtifact(ALPINE)
- image := fmt.Sprintf("%s/my-alpine", registryEndpoints[5].Address())
+ image := fmt.Sprintf("%s/my-alpine", ep.Address())
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
var buffer bytes.Buffer
- registryFileTmpl.Execute(&buffer, registryEndpoints[5])
+ registryFileTmpl.Execute(&buffer, ep)
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry5.conf", tempdir), buffer.Bytes(), 0644)
@@ -360,25 +345,25 @@ registries = ['{{.Host}}:{{.Port}}']`
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
- lock := GetPortLock(registryEndpoints[6].Port)
- defer lock.Unlock()
- registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[6].Port),
+ port := GetPort()
+ ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"}
+ registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port),
"--name", "registry6", registry})
registry.WaitWithDefaultTimeout()
Expect(registry).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry6", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port)
}
podmanTest.RestoreArtifact(ALPINE)
- image := fmt.Sprintf("%s/my-alpine", registryEndpoints[6].Address())
+ image := fmt.Sprintf("%s/my-alpine", ep.Address())
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
var buffer bytes.Buffer
- registryFileBadTmpl.Execute(&buffer, registryEndpoints[6])
+ registryFileBadTmpl.Execute(&buffer, ep)
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry6.conf", tempdir), buffer.Bytes(), 0644)
@@ -402,36 +387,36 @@ registries = ['{{.Host}}:{{.Port}}']`
if podmanTest.Host.Arch == "ppc64le" {
Skip("No registry image for ppc64le")
}
- lock7 := GetPortLock(registryEndpoints[7].Port)
- defer lock7.Unlock()
- lock8 := GetPortLock("6000")
- defer lock8.Unlock()
+ port1 := GetPort()
+ port2 := GetPort()
+ port3 := GetPort()
+ ep3 := endpoint{Port: fmt.Sprintf("%d", port3), Host: "localhost"}
- registryLocal := podmanTest.Podman([]string{"run", "-d", "--net=host", "-p", fmt.Sprintf("%s:5000", registryEndpoints[7].Port),
+ registryLocal := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d", port1),
"--name", "registry7", registry})
registryLocal.WaitWithDefaultTimeout()
Expect(registryLocal).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry7", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port1)
}
- registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", "6000:5000", "--name", "registry8", registry})
+ registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port2), "--name", "registry8", registry})
registryLocal.WaitWithDefaultTimeout()
Expect(registryLocal).Should(Exit(0))
if !WaitContainerReady(podmanTest, "registry8", "listening on", 20, 1) {
- Skip("Cannot start docker registry.")
+ Fail("Cannot start docker registry on port %s", port2)
}
podmanTest.RestoreArtifact(ALPINE)
- push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:6000/my-alpine"})
+ push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, fmt.Sprintf("localhost:%d/my-alpine", port2)})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
// registries.conf set up
var buffer bytes.Buffer
- registryFileTwoTmpl.Execute(&buffer, registryEndpoints[8])
+ registryFileTwoTmpl.Execute(&buffer, ep3)
podmanTest.setRegistriesConfigEnv(buffer.Bytes())
ioutil.WriteFile(fmt.Sprintf("%s/registry8.conf", tempdir), buffer.Bytes(), 0644)
diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go
index 8788369eb..7435a0e3b 100644
--- a/test/e2e/stats_test.go
+++ b/test/e2e/stats_test.go
@@ -185,6 +185,19 @@ var _ = Describe("Podman stats", func() {
Expect(session).Should(Exit(0))
})
+ It("podman reads slirp4netns network stats", func() {
+ session := podmanTest.Podman([]string{"run", "-d", "--network", "slirp4netns", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ cid := session.OutputToString()
+
+ stats := podmanTest.Podman([]string{"stats", "--format", "'{{.NetIO}}'", "--no-stream", cid})
+ stats.WaitWithDefaultTimeout()
+ Expect(stats).Should(Exit(0))
+ Expect(stats.OutputToString()).To(Not(ContainSubstring("-- / --")))
+ })
+
// Regression test for #8265
It("podman stats with custom memory limits", func() {
// Run three containers. One with a memory limit. Make sure
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
index 641f98c38..f413ce147 100644
--- a/test/e2e/system_reset_test.go
+++ b/test/e2e/system_reset_test.go
@@ -38,6 +38,10 @@ var _ = Describe("podman system reset", func() {
SkipIfRemote("system reset not supported on podman --remote")
// system reset will not remove additional store images, so need to grab length
+ // change the network dir so that we do not conflict with other tests
+ // that would use the same network dir and cause unnecessary flakes
+ podmanTest.NetworkConfigDir = tempdir
+
session := podmanTest.Podman([]string{"rmi", "--force", "--all"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -56,16 +60,16 @@ var _ = Describe("podman system reset", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"network", "create"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
session = podmanTest.Podman([]string{"system", "reset", "-f"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.ErrorToString()).To(Not(ContainSubstring("Failed to add pause process")))
- // If remote then the API service should have exited
- // On local tests this is a noop
- podmanTest.StartRemoteService()
-
session = podmanTest.Podman([]string{"images", "-n"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -80,5 +84,11 @@ var _ = Describe("podman system reset", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToStringArray()).To(BeEmpty())
+
+ session = podmanTest.Podman([]string{"network", "ls", "-q"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ // default network should exists
+ Expect(session.OutputToStringArray()).To(HaveLen(1))
})
})
diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go
index 966bc932a..0ac91abd3 100644
--- a/test/e2e/volume_create_test.go
+++ b/test/e2e/volume_create_test.go
@@ -144,7 +144,7 @@ var _ = Describe("Podman volume create", func() {
Expect(inspectGID).Should(Exit(0))
Expect(inspectGID.OutputToString()).To(Equal(gid))
- // options should containt `uid=3000,gid=4000:3000:4000`
+ // options should contain `uid=3000,gid=4000:3000:4000`
optionFormat := `{{ .Options.o }}:{{ .Options.UID }}:{{ .Options.GID }}`
optionStrFormatExpect := fmt.Sprintf(`uid=%s,gid=%s:%s:%s`, uid, gid, uid, gid)
inspectOpts := podmanTest.Podman([]string{"volume", "inspect", "--format", optionFormat, volName})
diff --git a/test/python/docker/__init__.py b/test/python/docker/__init__.py
index f75185192..816667b82 100644
--- a/test/python/docker/__init__.py
+++ b/test/python/docker/__init__.py
@@ -42,22 +42,25 @@ class Podman(object):
os.environ["CONTAINERS_REGISTRIES_CONF"] = os.path.join(
self.anchor_directory, "registry.conf"
)
- p = configparser.ConfigParser()
- p.read_dict(
- {
- "registries.search": {"registries": "['quay.io', 'docker.io']"},
- "registries.insecure": {"registries": "[]"},
- "registries.block": {"registries": "[]"},
- }
- )
+ conf = """unqualified-search-registries = ["docker.io", "quay.io"]
+
+[[registry]]
+location="localhost:5000"
+insecure=true
+
+[[registry.mirror]]
+location = "mirror.localhost:5000"
+
+"""
+
with open(os.environ["CONTAINERS_REGISTRIES_CONF"], "w") as w:
- p.write(w)
+ w.write(conf)
os.environ["CNI_CONFIG_PATH"] = os.path.join(
self.anchor_directory, "cni", "net.d"
)
os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True)
- self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"])
+ self.cmd.append("--network-config-dir=" + os.environ["CNI_CONFIG_PATH"])
cni_cfg = os.path.join(
os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist"
)
diff --git a/test/python/docker/compat/test_system.py b/test/python/docker/compat/test_system.py
index 131b18991..a928de0ee 100644
--- a/test/python/docker/compat/test_system.py
+++ b/test/python/docker/compat/test_system.py
@@ -54,7 +54,10 @@ class TestSystem(unittest.TestCase):
return super().tearDownClass()
def test_Info(self):
- self.assertIsNotNone(self.client.info())
+ info = self.client.info()
+ self.assertIsNotNone(info)
+ self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Secure"], False)
+ self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Mirrors"], ["mirror.localhost:5000"])
def test_info_container_details(self):
info = self.client.info()
diff --git a/test/system/005-info.bats b/test/system/005-info.bats
index 045045fa6..0f7e8b2e4 100644
--- a/test/system/005-info.bats
+++ b/test/system/005-info.bats
@@ -43,7 +43,6 @@ host.conmon.package | .*conmon.*
host.cgroupManager | \\\(systemd\\\|cgroupfs\\\)
host.cgroupVersion | v[12]
host.ociRuntime.path | $expr_path
-host.ociRuntime.package | .*\\\(crun\\\|runc\\\).*
store.configFile | $expr_path
store.graphDriverName | [a-z0-9]\\\+\\\$
store.graphRoot | $expr_path
@@ -89,6 +88,18 @@ host.slirp4netns.executable | $expr_path
is "$output" ".*graphOptions: {}" "output includes graphOptions: {}"
}
+@test "podman info netavark " {
+ # Confirm netavark in use when explicitely required by execution environment.
+ if [[ "$NETWORK_BACKEND" == "netavark" ]]; then
+ if ! is_netavark; then
+ # Assume is_netavark() will provide debugging feedback.
+ die "Netavark driver testing required, but not in use by podman."
+ fi
+ else
+ skip "Netavark testing not requested (\$NETWORK_BACKEND='$NETWORK_BACKEND')"
+ fi
+}
+
@test "podman --root PATH info - basic output" {
if ! is_remote; then
run_podman --storage-driver=vfs --root ${PODMAN_TMPDIR}/nothing-here-move-along info --format '{{ .Store.GraphOptions }}'
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 2d5ecab39..ec85ef166 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -5,18 +5,8 @@ load helpers
@test "podman run - basic tests" {
rand=$(random_string 30)
- # 2019-09 Fedora 31 and rawhide (32) are switching from runc to crun
- # because of cgroups v2; crun emits different error messages.
- # Default to runc:
- err_no_such_cmd="Error: .*: starting container process caused.*exec:.*stat /no/such/command: no such file or directory"
- err_no_exec_dir="Error: .*: starting container process caused.*exec:.* permission denied"
-
- # ...but check the configured runtime engine, and switch to crun as needed
- run_podman info --format '{{ .Host.OCIRuntime.Path }}'
- if expr "$output" : ".*/crun"; then
- err_no_such_cmd="Error: crun: executable file.* not found in \$PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found"
- err_no_exec_dir="Error: crun: open executable: Operation not permitted: OCI permission denied"
- fi
+ err_no_such_cmd="Error:.*/no/such/command.*[Nn]o such file or directory"
+ err_no_exec_dir="Error:.*exec.*permission denied"
tests="
true | 0 |
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index b1d181d50..8bf785081 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -80,26 +80,76 @@ verify_iid_and_name() {
@test "podman image scp transfer" {
skip_if_remote "only applicable under local podman"
+ if is_ubuntu; then
+ skip "I don't have time to deal with this"
+ fi
- skip "FIXME FIXME FIXME: this needs a big rewrite"
-
- get_iid_and_name
+ # The testing is the same whether we're root or rootless; all that
+ # differs is the destination (not-me) username.
if is_rootless; then
+ # Simple: push to root.
whoami=$(id -un)
- # FIXME: first, test that we can sudo. If we can't, skip.
- # FIXME: test 'scp $IMAGE root@localhost::'
- # FIXME: then test the rest
- # FIXME: check output
- run_podman image scp $whoami@localhost::$iid root@localhost::
- is "$output" "Loaded image.*: $iid" "...."
-
- # FIXME: "-q" is a NOP
- run_podman image scp -q $whoami@localhost::$iid root@localhost::
+ notme=root
+ _sudo() { command sudo -n "$@"; }
else
- # root
- # FIXME: identify a rootless user. DO NOT CREATE ONE.
- run_podman image scp root@localhost::$iid 1000:1000@localhost::
+ # Harder: our CI infrastructure needs to define this & set up the acct
+ whoami=root
+ notme=${PODMAN_ROOTLESS_USER}
+ if [[ -z "$notme" ]]; then
+ skip "To run this test, set PODMAN_ROOTLESS_USER to a safe username"
+ fi
+ _sudo() { command sudo -n -u "$notme" "$@"; }
fi
+
+ # If we can't sudo, we can't test.
+ _sudo true || skip "cannot sudo to $notme"
+
+ # Preserve digest of original image; we will compare against it later
+ run_podman image inspect --format '{{.Digest}}' $IMAGE
+ src_digest=$output
+
+ # image name that is not likely to exist in the destination
+ newname=foo.bar/nonesuch/c_$(random_string 10 | tr A-Z a-z):mytag
+ run_podman tag $IMAGE $newname
+
+ # Copy it there.
+ run_podman image scp $newname ${notme}@localhost::
+ is "$output" "Copying blob .*Copying config.*Writing manifest.*Storing signatures"
+
+ # confirm that image was copied. FIXME: also try $PODMAN image inspect?
+ _sudo $PODMAN image exists $newname
+
+ # Copy it back, this time using -q
+ run_podman untag $IMAGE $newname
+ run_podman image scp -q ${notme}@localhost::$newname
+
+ expect="Loaded image(s): $newname"
+ is "$output" "$expect" "-q silences output"
+
+ # Confirm that we have it, and that its digest matches our original
+ run_podman image inspect --format '{{.Digest}}' $newname
+ is "$output" "$src_digest" "Digest of re-fetched image matches original"
+
+ # Clean up
+ _sudo $PODMAN image rm $newname
+ run_podman untag $IMAGE $newname
+
+ # Negative test for nonexistent image.
+ # FIXME: error message is 2 lines, the 2nd being "exit status 125".
+ # FIXME: is that fixable, or do we have to live with it?
+ nope="nope.nope/nonesuch:notag"
+ run_podman 125 image scp ${notme}@localhost::$nope
+ is "$output" "Error: $nope: image not known.*" "Pulling nonexistent image"
+
+ run_podman 125 image scp $nope ${notme}@localhost::
+ is "$output" "Error: $nope: image not known.*" "Pushing nonexistent image"
+
+ # Negative test for copying to a different name
+ run_podman 125 image scp $IMAGE ${notme}@localhost::newname:newtag
+ is "$output" "Error: cannot specify an image rename: invalid argument" \
+ "Pushing with a different name: not allowed"
+
+ # FIXME: any point in copying by image ID? What else should we test?
}
diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats
index b6030ba3c..a3c972b3e 100644
--- a/test/system/160-volumes.bats
+++ b/test/system/160-volumes.bats
@@ -213,6 +213,8 @@ EOF
# Podman volume user test
@test "podman volume user test" {
is_rootless || skip "only meaningful when run rootless"
+ skip_if_remote "not applicable on podman-remote"
+
user="1000:2000"
newuser="100:200"
tmpdir=${PODMAN_TMPDIR}/volume_$(random_string)
@@ -375,7 +377,7 @@ NeedsChown | true
run_podman run --rm --volume $myvolume:/etc $IMAGE ls /etc/passwd
run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume
- is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happend and be false"
+ is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happened and be false"
run_podman volume inspect --format '{{.Mountpoint}}' $myvolume
mountpoint="$output"
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index b40359193..34dfaa8f6 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -29,8 +29,7 @@ function teardown() {
}
@test "podman pod top - containers in different PID namespaces" {
- # With infra=false, we don't get a /pause container (we also
- # don't pull k8s.gcr.io/pause )
+ # With infra=false, we don't get a /pause container
no_infra='--infra=false'
run_podman pod create $no_infra
podid="$output"
@@ -148,9 +147,6 @@ EOF
# Pod no longer exists
run_podman 1 pod exists $podid
run_podman 1 pod exists $podname
-
- # Pause image hasn't been pulled
- run_podman 1 image exists k8s.gcr.io/pause:3.5
}
# Random byte
@@ -329,8 +325,6 @@ EOF
local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
local pod_name="$(random_string 10 | tr A-Z a-z)"
- # Note that the internal pause image is built even when --infra-image is
- # set to the K8s one.
run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5"
is "$output" "" "output should be empty"
run_podman '?' pod create --infra-name "$infra_name"
@@ -339,9 +333,6 @@ EOF
fi
run_podman pod rm -f $pod_name
run_podman images -a
-
- # Pause image hasn't been pulled
- run_podman 1 image exists k8s.gcr.io/pause:3.5
}
@test "podman pod create --share" {
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index 7540270bd..5a8bf4218 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -373,8 +373,10 @@ EOF
systemctl enable --now podman-auto-update-$cname.timer
systemctl list-timers --all
- # While systemd v245 and later uses 'Finished', older versions uses 'Started' for oneshot services
- local expect='(Finished|Started) Podman auto-update testing service'
+ # systemd <245 displays 'Started Podman auto-update ...'
+ # systemd 245 - <250 displays 'Finished Podman auto-update ...'
+ # systemd 250 - ???? displays 'Finished <unit name> - Podman auto-...'
+ local expect='(Started|Finished.*) Podman auto-update testing service'
local failed_start=failed
local count=0
while [ $count -lt 120 ]; do
diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats
index 4e9ac4dd6..7b70f60f4 100644
--- a/test/system/272-system-connection.bats
+++ b/test/system/272-system-connection.bats
@@ -124,10 +124,14 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true" \
# If we have ssh access to localhost (unlikely in CI), test that.
@test "podman system connection - ssh" {
- rand=$(random_string 20)
- echo $rand >$PODMAN_TMPDIR/testfile
+ # system connection only really works if we have an agent
+ run ssh-add -l
+ test "$status" -eq 0 || skip "Not running under ssh-agent"
+ test "${#lines[@]}" -ge 1 || skip "ssh agent has no identities"
# Can we actually ssh to localhost?
+ rand=$(random_string 20)
+ echo $rand >$PODMAN_TMPDIR/testfile
run ssh -q -o BatchMode=yes \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index dbdfd4b9d..056a056f6 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -245,7 +245,8 @@ function check_label() {
is "$output" "system_u:object_r:container_file_t:$level $tmpdir" \
"Confined Relabel Correctly"
- if is_rootless; then
+ # podman-remote has no 'unshare'
+ if is_rootless && ! is_remote; then
run_podman unshare touch $tmpdir/test1
# Relabel entire directory
run_podman unshare chcon system_u:object_r:usr_t:s0 $tmpdir
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 5a721c965..9b39ebf97 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -256,13 +256,17 @@ load helpers
# rootless cannot modify iptables
if ! is_rootless; then
- # flush the CNI iptables here
- run iptables -t nat -F CNI-HOSTPORT-DNAT
+ # flush the port forwarding iptable rule here
+ chain="CNI-HOSTPORT-DNAT"
+ if is_netavark; then
+ chain="NETAVARK-HOSTPORT-DNAT"
+ fi
+ run iptables -t nat -F "$chain"
# check that we cannot curl (timeout after 5 sec)
run timeout 5 curl -s $SERVER/index.txt
if [ "$status" -ne 124 ]; then
- die "curl did not timeout, status code: $status"
+ die "curl did not timeout, status code: $status"
fi
fi
@@ -589,4 +593,25 @@ load helpers
run_podman network rm -t 0 -f $netname
}
+@test "podman run CONTAINERS_CONF dns options" {
+ skip_if_remote "CONTAINERS_CONF redirect does not work on remote"
+ # Test on the CLI and via containers.conf
+ containersconf=$PODMAN_TMPDIR/containers.conf
+
+ searchIP="100.100.100.100"
+ cat >$containersconf <<EOF
+[containers]
+ dns_searches = [ "example.com"]
+ dns_servers = [
+ "1.1.1.1",
+ "$searchIP",
+ "1.0.0.1",
+ "8.8.8.8",
+]
+EOF
+ CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE grep "example.com" /etc/resolv.conf
+ CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE grep $searchIP /etc/resolv.conf
+ is "$output" "nameserver $searchIP" "Should only be one $searchIP not multiple"
+}
+
# vim: filetype=sh
diff --git a/test/system/README.md b/test/system/README.md
index fe6d1ed52..76626b6dd 100644
--- a/test/system/README.md
+++ b/test/system/README.md
@@ -49,6 +49,7 @@ Running tests
To run the tests locally in your sandbox, you can use one of these methods:
* make;PODMAN=./bin/podman bats ./test/system/070-build.bats # runs just the specified test
* make;PODMAN=./bin/podman bats ./test/system # runs all
+* make;PODMAN=./bin/podman NETWORK_BACKEND=netavark bats ./test/system # Assert & enable netavark testing
To test as root:
* $ PODMAN=./bin/podman sudo --preserve-env=PODMAN bats test/system
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 36a88fc10..c622a5172 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -341,6 +341,15 @@ function is_cgroupsv2() {
test "$cgroup_type" = "cgroup2fs"
}
+# True if podman is using netavark
+function is_netavark() {
+ run_podman info --format '{{.Host.NetworkBackend}}'
+ if [[ "$output" =~ netavark ]]; then
+ return 0
+ fi
+ return 1
+}
+
# Returns the OCI runtime *basename* (typically crun or runc). Much as we'd
# love to cache this result, we probably shouldn't.
function podman_runtime() {
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 1f5067950..14092a2a5 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -12,12 +12,34 @@ import (
"strings"
"time"
+ "github.com/sirupsen/logrus"
+
"github.com/containers/storage/pkg/parsers/kernel"
. "github.com/onsi/ginkgo" //nolint:golint,stylecheck
. "github.com/onsi/gomega" //nolint:golint,stylecheck
. "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck
)
+type NetworkBackend int
+
+const (
+ // Container Networking backend
+ CNI NetworkBackend = iota
+ // Netavark network backend
+ Netavark NetworkBackend = iota
+)
+
+func (n NetworkBackend) ToString() string {
+ switch n {
+ case CNI:
+ return "cni"
+ case Netavark:
+ return "netavark"
+ }
+ logrus.Errorf("unknown network backend: %q", n)
+ return ""
+}
+
var (
DefaultWaitTimeout = 90
OSReleasePath = "/etc/os-release"
@@ -34,17 +56,18 @@ type PodmanTestCommon interface {
// PodmanTest struct for command line options
type PodmanTest struct {
- PodmanMakeOptions func(args []string, noEvents, noCache bool) []string
+ ImageCacheDir string
+ ImageCacheFS string
+ NetworkBackend NetworkBackend
PodmanBinary string
- TempDir string
- RemoteTest bool
+ PodmanMakeOptions func(args []string, noEvents, noCache bool) []string
+ RemoteCommand *exec.Cmd
RemotePodmanBinary string
RemoteSession *os.Process
RemoteSocket string
RemoteSocketLock string // If not "", should be removed _after_ RemoteSocket is removed
- RemoteCommand *exec.Cmd
- ImageCacheDir string
- ImageCacheFS string
+ RemoteTest bool
+ TempDir string
}
// PodmanSession wraps the gexec.session so we can extend it
@@ -73,8 +96,10 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
if p.RemoteTest {
podmanBinary = p.RemotePodmanBinary
}
-
runCmd := append(wrapper, podmanBinary)
+ if p.NetworkBackend == Netavark {
+ runCmd = append(runCmd, []string{"--network-backend", "netavark"}...)
+ }
if p.RemoteTest {
podmanOptions = append([]string{"--remote", "--url", p.RemoteSocket}, podmanOptions...)
}
diff --git a/troubleshooting.md b/troubleshooting.md
index 2f5eb6552..82ca64305 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -689,7 +689,7 @@ file `/etc/systemd/system/user@.service.d/delegate.conf` with the contents:
[Service]
Delegate=memory pids cpu io
-After logging out and loggin back in, you should have permission to set CPU
+After logging out and logging back in, you should have permission to set CPU
limits.
### 26) `exec container process '/bin/sh': Exec format error` (or another binary than `bin/sh`)
@@ -907,3 +907,15 @@ Resolution steps
* Before invoking Podman command create a valid login session for your rootless user using `loginctl enable-linger <username>`
* If `loginctl` is unavailable you can also try logging in via `ssh` i.e `ssh <username>@localhost`.
+
+### 31) 127.0.0.1:7777 port already bound
+
+After deleting a VM on macOS, the initialization of subsequent VMs fails.
+
+#### Symptom
+
+After deleting a client VM on macOS via `podman machine stop` && `podman machine rm`, attempting to `podman machine init` a new client VM leads to an error with the 127.0.0.1:7777 port already bound.
+
+### Solution
+
+You will need to remove the hanging gv-proxy process bound to the port in question. For example, if the port mentioned in the error message is 127.0.0.1:7777, you can use the command `kill -9 $(lsof -i:7777)` in order to identify and remove the hanging process which prevents you from starting a new VM on that default port.
diff --git a/utils/utils.go b/utils/utils.go
index caf63c975..52586b937 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -238,3 +238,18 @@ func CreateSCPCommand(cmd *exec.Cmd, command []string) *exec.Cmd {
cmd.Stdout = os.Stdout
return cmd
}
+
+// LoginUser starts the user process on the host so that image scp can use systemd-run
+func LoginUser(user string) (*exec.Cmd, error) {
+ sleep, err := exec.LookPath("sleep")
+ if err != nil {
+ return nil, err
+ }
+ machinectl, err := exec.LookPath("machinectl")
+ if err != nil {
+ return nil, err
+ }
+ cmd := exec.Command(machinectl, "shell", "-q", user+"@.host", sleep, "inf")
+ err = cmd.Start()
+ return cmd, err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/.golangci.yml b/vendor/github.com/Microsoft/hcsshim/.golangci.yml
index 16b25be55..2400e7f1e 100644
--- a/vendor/github.com/Microsoft/hcsshim/.golangci.yml
+++ b/vendor/github.com/Microsoft/hcsshim/.golangci.yml
@@ -1,3 +1,6 @@
+run:
+ timeout: 8m
+
linters:
enable:
- stylecheck
diff --git a/vendor/github.com/Microsoft/hcsshim/go.mod b/vendor/github.com/Microsoft/hcsshim/go.mod
index 7c9747667..9c60dd302 100644
--- a/vendor/github.com/Microsoft/hcsshim/go.mod
+++ b/vendor/github.com/Microsoft/hcsshim/go.mod
@@ -29,7 +29,7 @@ require (
go.opencensus.io v0.22.3
golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
- golang.org/x/sys v0.0.0-20210510120138-977fb7262007
+ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
google.golang.org/grpc v1.40.0
)
diff --git a/vendor/github.com/Microsoft/hcsshim/go.sum b/vendor/github.com/Microsoft/hcsshim/go.sum
index 7c383806d..93c37657f 100644
--- a/vendor/github.com/Microsoft/hcsshim/go.sum
+++ b/vendor/github.com/Microsoft/hcsshim/go.sum
@@ -812,8 +812,9 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
index 644f0ab71..e21354ffd 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
@@ -78,6 +78,13 @@ var (
// ErrNotSupported is an error encountered when hcs doesn't support the request
ErrPlatformNotSupported = errors.New("unsupported platform request")
+
+ // ErrProcessAlreadyStopped is returned by hcs if the process we're trying to kill has already been stopped.
+ ErrProcessAlreadyStopped = syscall.Errno(0x8037011f)
+
+ // ErrInvalidHandle is an error that can be encountrered when querying the properties of a compute system when the handle to that
+ // compute system has already been closed.
+ ErrInvalidHandle = syscall.Errno(0x6)
)
type ErrorEvent struct {
@@ -249,6 +256,14 @@ func IsNotExist(err error) bool {
err == ErrElementNotFound
}
+// IsErrorInvalidHandle checks whether the error is the result of an operation carried
+// out on a handle that is invalid/closed. This error popped up while trying to query
+// stats on a container in the process of being stopped.
+func IsErrorInvalidHandle(err error) bool {
+ err = getInnerError(err)
+ return err == ErrInvalidHandle
+}
+
// IsAlreadyClosed checks if an error is caused by the Container or Process having been
// already closed by a call to the Close() method.
func IsAlreadyClosed(err error) bool {
@@ -281,6 +296,7 @@ func IsTimeout(err error) bool {
func IsAlreadyStopped(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeAlreadyStopped ||
+ err == ErrProcessAlreadyStopped ||
err == ErrElementNotFound
}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
index 8f2034668..f4605922a 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
@@ -3,7 +3,9 @@ package hcs
import (
"context"
"encoding/json"
+ "errors"
"io"
+ "os"
"sync"
"syscall"
"time"
@@ -16,16 +18,17 @@ import (
// ContainerError is an error encountered in HCS
type Process struct {
- handleLock sync.RWMutex
- handle vmcompute.HcsProcess
- processID int
- system *System
- hasCachedStdio bool
- stdioLock sync.Mutex
- stdin io.WriteCloser
- stdout io.ReadCloser
- stderr io.ReadCloser
- callbackNumber uintptr
+ handleLock sync.RWMutex
+ handle vmcompute.HcsProcess
+ processID int
+ system *System
+ hasCachedStdio bool
+ stdioLock sync.Mutex
+ stdin io.WriteCloser
+ stdout io.ReadCloser
+ stderr io.ReadCloser
+ callbackNumber uintptr
+ killSignalDelivered bool
closedWaitOnce sync.Once
waitBlock chan struct{}
@@ -149,12 +152,45 @@ func (process *Process) Kill(ctx context.Context) (bool, error) {
return false, makeProcessError(process, operation, ErrAlreadyClosed, nil)
}
+ if process.killSignalDelivered {
+ // A kill signal has already been sent to this process. Sending a second
+ // one offers no real benefit, as processes cannot stop themselves from
+ // being terminated, once a TerminateProcess has been issued. Sending a
+ // second kill may result in a number of errors (two of which detailed bellow)
+ // and which we can avoid handling.
+ return true, nil
+ }
+
resultJSON, err := vmcompute.HcsTerminateProcess(ctx, process.handle)
+ if err != nil {
+ // We still need to check these two cases, as processes may still be killed by an
+ // external actor (human operator, OOM, random script etc).
+ if errors.Is(err, os.ErrPermission) || IsAlreadyStopped(err) {
+ // There are two cases where it should be safe to ignore an error returned
+ // by HcsTerminateProcess. The first one is cause by the fact that
+ // HcsTerminateProcess ends up calling TerminateProcess in the context
+ // of a container. According to the TerminateProcess documentation:
+ // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminateprocess#remarks
+ // After a process has terminated, call to TerminateProcess with open
+ // handles to the process fails with ERROR_ACCESS_DENIED (5) error code.
+ // It's safe to ignore this error here. HCS should always have permissions
+ // to kill processes inside any container. So an ERROR_ACCESS_DENIED
+ // is unlikely to be anything else than what the ending remarks in the
+ // documentation states.
+ //
+ // The second case is generated by hcs itself, if for any reason HcsTerminateProcess
+ // is called twice in a very short amount of time. In such cases, hcs may return
+ // HCS_E_PROCESS_ALREADY_STOPPED.
+ return true, nil
+ }
+ }
events := processHcsResult(ctx, resultJSON)
delivered, err := process.processSignalResult(ctx, err)
if err != nil {
err = makeProcessError(process, operation, err, events)
}
+
+ process.killSignalDelivered = delivered
return delivered, err
}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/console.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/console.go
new file mode 100644
index 000000000..def952541
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/console.go
@@ -0,0 +1,44 @@
+package winapi
+
+import (
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+const PSEUDOCONSOLE_INHERIT_CURSOR = 0x1
+
+// CreatePseudoConsole creates a windows pseudo console.
+func CreatePseudoConsole(size windows.Coord, hInput windows.Handle, hOutput windows.Handle, dwFlags uint32, hpcon *windows.Handle) error {
+ // We need this wrapper as the function takes a COORD struct and not a pointer to one, so we need to cast to something beforehand.
+ return createPseudoConsole(*((*uint32)(unsafe.Pointer(&size))), hInput, hOutput, 0, hpcon)
+}
+
+// ResizePseudoConsole resizes the internal buffers of the pseudo console to the width and height specified in `size`.
+func ResizePseudoConsole(hpcon windows.Handle, size windows.Coord) error {
+ // We need this wrapper as the function takes a COORD struct and not a pointer to one, so we need to cast to something beforehand.
+ return resizePseudoConsole(hpcon, *((*uint32)(unsafe.Pointer(&size))))
+}
+
+// HRESULT WINAPI CreatePseudoConsole(
+// _In_ COORD size,
+// _In_ HANDLE hInput,
+// _In_ HANDLE hOutput,
+// _In_ DWORD dwFlags,
+// _Out_ HPCON* phPC
+// );
+//
+//sys createPseudoConsole(size uint32, hInput windows.Handle, hOutput windows.Handle, dwFlags uint32, hpcon *windows.Handle) (hr error) = kernel32.CreatePseudoConsole
+
+// void WINAPI ClosePseudoConsole(
+// _In_ HPCON hPC
+// );
+//
+//sys ClosePseudoConsole(hpc windows.Handle) = kernel32.ClosePseudoConsole
+
+// HRESULT WINAPI ResizePseudoConsole(
+// _In_ HPCON hPC ,
+// _In_ COORD size
+// );
+//
+//sys resizePseudoConsole(hPc windows.Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go
index b87068327..37839435b 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go
@@ -2,9 +2,7 @@ package winapi
const PROCESS_ALL_ACCESS uint32 = 2097151
-// DWORD GetProcessImageFileNameW(
-// HANDLE hProcess,
-// LPWSTR lpImageFileName,
-// DWORD nSize
-// );
-//sys GetProcessImageFileName(hProcess windows.Handle, imageFileName *uint16, nSize uint32) (size uint32, err error) = kernel32.GetProcessImageFileNameW
+const (
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x20016
+ PROC_THREAD_ATTRIBUTE_JOB_LIST = 0x2000D
+)
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go
index ec88c0d21..1d4ba3c4f 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go
@@ -2,4 +2,4 @@
// be thought of as an extension to golang.org/x/sys/windows.
package winapi
-//go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go system.go net.go path.go thread.go iocp.go jobobject.go logon.go memory.go process.go processor.go devices.go filesystem.go errors.go
+//go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go console.go system.go net.go path.go thread.go iocp.go jobobject.go logon.go memory.go process.go processor.go devices.go filesystem.go errors.go
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go
index 59ddee274..4eb64b4c0 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go
@@ -37,12 +37,15 @@ func errnoErr(e syscall.Errno) error {
}
var (
+ modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modcfgmgr32 = windows.NewLazySystemDLL("cfgmgr32.dll")
+ procCreatePseudoConsole = modkernel32.NewProc("CreatePseudoConsole")
+ procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole")
+ procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole")
procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
procSetJobCompartmentId = modiphlpapi.NewProc("SetJobCompartmentId")
procSearchPathW = modkernel32.NewProc("SearchPathW")
@@ -58,7 +61,6 @@ var (
procLogonUserW = modadvapi32.NewProc("LogonUserW")
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
procLocalFree = modkernel32.NewProc("LocalFree")
- procGetProcessImageFileNameW = modkernel32.NewProc("GetProcessImageFileNameW")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procCM_Get_Device_ID_List_SizeA = modcfgmgr32.NewProc("CM_Get_Device_ID_List_SizeA")
procCM_Get_Device_ID_ListA = modcfgmgr32.NewProc("CM_Get_Device_ID_ListA")
@@ -71,6 +73,33 @@ var (
procRtlNtStatusToDosError = modntdll.NewProc("RtlNtStatusToDosError")
)
+func createPseudoConsole(size uint32, hInput windows.Handle, hOutput windows.Handle, dwFlags uint32, hpcon *windows.Handle) (hr error) {
+ r0, _, _ := syscall.Syscall6(procCreatePseudoConsole.Addr(), 5, uintptr(size), uintptr(hInput), uintptr(hOutput), uintptr(dwFlags), uintptr(unsafe.Pointer(hpcon)), 0)
+ if int32(r0) < 0 {
+ if r0&0x1fff0000 == 0x00070000 {
+ r0 &= 0xffff
+ }
+ hr = syscall.Errno(r0)
+ }
+ return
+}
+
+func ClosePseudoConsole(hpc windows.Handle) {
+ syscall.Syscall(procClosePseudoConsole.Addr(), 1, uintptr(hpc), 0, 0)
+ return
+}
+
+func resizePseudoConsole(hPc windows.Handle, size uint32) (hr error) {
+ r0, _, _ := syscall.Syscall(procResizePseudoConsole.Addr(), 2, uintptr(hPc), uintptr(size), 0)
+ if int32(r0) < 0 {
+ if r0&0x1fff0000 == 0x00070000 {
+ r0 &= 0xffff
+ }
+ hr = syscall.Errno(r0)
+ }
+ return
+}
+
func NtQuerySystemInformation(systemInfoClass int, systemInformation uintptr, systemInfoLength uint32, returnLength *uint32) (status uint32) {
r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInfoClass), uintptr(systemInformation), uintptr(systemInfoLength), uintptr(unsafe.Pointer(returnLength)), 0, 0)
status = uint32(r0)
@@ -227,19 +256,6 @@ func LocalFree(ptr uintptr) {
return
}
-func GetProcessImageFileName(hProcess windows.Handle, imageFileName *uint16, nSize uint32) (size uint32, err error) {
- r0, _, e1 := syscall.Syscall(procGetProcessImageFileNameW.Addr(), 3, uintptr(hProcess), uintptr(unsafe.Pointer(imageFileName)), uintptr(nSize))
- size = uint32(r0)
- if size == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
func GetActiveProcessorCount(groupNumber uint16) (amount uint32) {
r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0)
amount = uint32(r0)
diff --git a/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go b/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
index 49fb740cd..75dce5d82 100644
--- a/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
+++ b/vendor/github.com/Microsoft/hcsshim/osversion/windowsbuilds.go
@@ -38,4 +38,13 @@ const (
// V21H1 corresponds to Windows Server 21H1 (semi-annual channel).
V21H1 = 19043
+
+ // V21H2Win10 corresponds to Windows 10 (November 2021 Update).
+ V21H2Win10 = 19044
+
+ // V21H2Server corresponds to Windows Server 2022 (ltsc2022).
+ V21H2Server = 20348
+
+ // V21H2Win11 corresponds to Windows 11 (original release).
+ V21H2Win11 = 22000
)
diff --git a/vendor/github.com/buger/goterm/.gitignore b/vendor/github.com/buger/goterm/.gitignore
new file mode 100644
index 000000000..1377554eb
--- /dev/null
+++ b/vendor/github.com/buger/goterm/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/vendor/github.com/buger/goterm/box.go b/vendor/github.com/buger/goterm/box.go
index 7df929d7d..4a119c552 100644
--- a/vendor/github.com/buger/goterm/box.go
+++ b/vendor/github.com/buger/goterm/box.go
@@ -2,7 +2,9 @@ package goterm
import (
"bytes"
+ "regexp"
"strings"
+ _ "unicode/utf8"
)
const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
@@ -61,7 +63,9 @@ func (b *Box) Write(p []byte) (int, error) {
return b.Buf.Write(p)
}
-// Render Box
+var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`)
+
+// String renders Box
func (b *Box) String() (out string) {
borders := strings.Split(b.Border, " ")
lines := strings.Split(b.Buf.String(), "\n")
@@ -74,7 +78,6 @@ func (b *Box) String() (out string) {
// Content width without borders and padding
contentWidth := b.Width - (b.PaddingX+1)*2
-
for y := 0; y < b.Height; y++ {
var line string
@@ -99,12 +102,63 @@ func (b *Box) String() (out string) {
line = ""
}
- if len(line) > contentWidth-1 {
+ r := []rune(line)
+
+ lastAnsii := ""
+ withoutAnsii := []rune{}
+ withOffset := []rune{}
+ i := 0
+
+ for {
+ if i >= len(r) {
+ break
+ }
+
+ if r[i] == 27 {
+ lastAnsii = ""
+ withOffset = append(withOffset, r[i])
+ lastAnsii += string(r[i])
+ i++
+ for {
+
+ i++
+ if i > len(r) {
+ break
+ }
+
+ withOffset = append(withOffset, r[i])
+ lastAnsii += string(r[i])
+
+ if r[i] == 'm' {
+ i++
+ break
+ }
+ }
+ }
+
+ if i >= len(r) {
+ break
+ }
+
+ withoutAnsii = append(withoutAnsii, r[i])
+
+ if len(withoutAnsii) <= contentWidth {
+ withOffset = append(withOffset, r[i])
+ }
+
+ i++
+ }
+
+ if len(withoutAnsii) > contentWidth {
// If line is too large limit it
- line = line[0:contentWidth]
+ line = string(withOffset)
} else {
// If line is too small enlarge it by adding spaces
- line = line + strings.Repeat(" ", contentWidth-len(line))
+ line += strings.Repeat(" ", contentWidth-len(withoutAnsii))
+ }
+
+ if lastAnsii != "" {
+ line += RESET
}
line = prefix + line + suffix
@@ -112,7 +166,7 @@ func (b *Box) String() (out string) {
// Don't add newline for last element
if y != b.Height-1 {
- line = line + "\n"
+ line += "\n"
}
out += line
diff --git a/vendor/github.com/buger/goterm/go.mod b/vendor/github.com/buger/goterm/go.mod
new file mode 100644
index 000000000..47f0e68b9
--- /dev/null
+++ b/vendor/github.com/buger/goterm/go.mod
@@ -0,0 +1,5 @@
+module github.com/buger/goterm
+
+go 1.15
+
+require golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54
diff --git a/vendor/github.com/buger/goterm/go.sum b/vendor/github.com/buger/goterm/go.sum
new file mode 100644
index 000000000..a9c9b7f42
--- /dev/null
+++ b/vendor/github.com/buger/goterm/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/buger/goterm/plot.go b/vendor/github.com/buger/goterm/plot.go
index 120147623..504358cbe 100644
--- a/vendor/github.com/buger/goterm/plot.go
+++ b/vendor/github.com/buger/goterm/plot.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math"
"strings"
+ "unicode/utf8"
)
const (
@@ -119,7 +120,7 @@ func (c *LineChart) DrawAxes(maxX, minX, maxY, minY float64, index int) {
c.writeText(ff(minX), c.paddingX, 0)
x_col := c.data.columns[0]
- c.writeText(c.data.columns[0], c.Width/2-len(x_col)/2, 1)
+ c.writeText(c.data.columns[0], c.Width/2-utf8.RuneCountInString(x_col)/2, 1)
if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 {
col := c.data.columns[index]
diff --git a/vendor/github.com/buger/goterm/terminal.go b/vendor/github.com/buger/goterm/terminal.go
index 7c4dfa70f..1ba6493ad 100644
--- a/vendor/github.com/buger/goterm/terminal.go
+++ b/vendor/github.com/buger/goterm/terminal.go
@@ -71,7 +71,7 @@ type winsize struct {
// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
var Screen *bytes.Buffer = new(bytes.Buffer)
-// Get relative or absolute coordinates
+// GetXY gets relative or absolute coordinates
// To get relative, set PCT flag to number:
//
// // Get 10% of total width to `x` and 20 to y
@@ -145,7 +145,7 @@ func MoveTo(str string, x int, y int) (out string) {
})
}
-// Return carrier to start of line
+// ResetLine returns carrier to start of line
func ResetLine(str string) (out string) {
return applyTransform(str, func(idx int, line string) string {
return fmt.Sprintf("%s%s", RESET_LINE, line)
@@ -188,7 +188,7 @@ func Background(str string, color int) string {
})
}
-// Get console width
+// Width gets console width
func Width() int {
ws, err := getWinsize()
@@ -199,7 +199,7 @@ func Width() int {
return int(ws.Col)
}
-// Get console height
+// Height gets console height
func Height() int {
ws, err := getWinsize()
if err != nil {
@@ -208,7 +208,7 @@ func Height() int {
return int(ws.Row)
}
-// Get current height. Line count in Screen buffer.
+// CurrentHeight gets current height. Line count in Screen buffer.
func CurrentHeight() int {
return strings.Count(Screen.String(), "\n")
}
diff --git a/vendor/github.com/buger/goterm/terminal_nosysioctl.go b/vendor/github.com/buger/goterm/terminal_nosysioctl.go
index 690615008..9b988ffd5 100644
--- a/vendor/github.com/buger/goterm/terminal_nosysioctl.go
+++ b/vendor/github.com/buger/goterm/terminal_nosysioctl.go
@@ -1,4 +1,4 @@
-// +build windows plan9 solaris
+// +build plan9 solaris
package goterm
diff --git a/vendor/github.com/buger/goterm/terminal_sysioctl.go b/vendor/github.com/buger/goterm/terminal_sysioctl.go
index 5a61cd52b..33148ede0 100644
--- a/vendor/github.com/buger/goterm/terminal_sysioctl.go
+++ b/vendor/github.com/buger/goterm/terminal_sysioctl.go
@@ -4,6 +4,7 @@ package goterm
import (
"os"
+
"golang.org/x/sys/unix"
)
diff --git a/vendor/github.com/buger/goterm/terminal_windows.go b/vendor/github.com/buger/goterm/terminal_windows.go
new file mode 100644
index 000000000..37c56ae69
--- /dev/null
+++ b/vendor/github.com/buger/goterm/terminal_windows.go
@@ -0,0 +1,23 @@
+// +build windows
+
+package goterm
+
+import (
+ "os"
+
+ "golang.org/x/sys/windows"
+)
+
+func getWinsize() (*winsize, error) {
+ ws := new(winsize)
+ fd := os.Stdout.Fd()
+ var info windows.ConsoleScreenBufferInfo
+ if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+ return nil, err
+ }
+
+ ws.Col = uint16(info.Window.Right - info.Window.Left + 1)
+ ws.Row = uint16(info.Window.Bottom - info.Window.Top + 1)
+
+ return ws, nil
+}
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
index e56319545..2c36e89b4 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
@@ -107,7 +107,7 @@ type Telemetry struct {
}
// Open opens a stargz file for reading.
-// The behaviour is configurable using options.
+// The behavior is configurable using options.
//
// Note that each entry name is normalized as the path that is relative to root.
func Open(sr *io.SectionReader, opt ...OpenOption) (*Reader, error) {
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod
index 144d022ba..b82879fd7 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod
@@ -3,7 +3,7 @@ module github.com/containerd/stargz-snapshotter/estargz
go 1.16
require (
- github.com/klauspost/compress v1.13.6
+ github.com/klauspost/compress v1.14.2
github.com/opencontainers/go-digest v1.0.0
github.com/pkg/errors v0.9.1
github.com/vbatts/tar-split v0.11.2
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum
index d3c934ff8..20433e16b 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum
@@ -1,8 +1,8 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
-github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
+github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
diff --git a/vendor/github.com/containers/buildah/.cirrus.yml b/vendor/github.com/containers/buildah/.cirrus.yml
index b3be43a2d..ec954630c 100644
--- a/vendor/github.com/containers/buildah/.cirrus.yml
+++ b/vendor/github.com/containers/buildah/.cirrus.yml
@@ -29,7 +29,7 @@ env:
PRIOR_FEDORA_NAME: "fedora-34"
UBUNTU_NAME: "ubuntu-2110"
- IMAGE_SUFFIX: "c6226133906620416"
+ IMAGE_SUFFIX: "c4560539387953152"
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}"
@@ -128,13 +128,35 @@ vendor_task:
- './hack/tree_status.sh'
+# Confirm cross-compile ALL architectures on a Mac OS-X VM.
+cross_build_task:
+ name: "Cross Compile"
+ alias: cross_build
+ only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
+
+ osx_instance:
+ image: 'big-sur-base'
+
+ script:
+ - brew update
+ - brew install go
+ - brew install go-md2man
+ - brew install gpgme
+ - go version
+ - make cross CGO_ENABLED=0
+
+ binary_artifacts:
+ path: ./bin/*
+
+
unit_task:
name: 'Unit tests w/ $STORAGE_DRIVER'
alias: unit
- only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
- depends_on:
+ only_if: *not_docs
+ depends_on: &smoke_vendor_cross
- smoke
- vendor
+ - cross_build
timeout_in: 1h
@@ -156,8 +178,7 @@ conformance_task:
name: 'Build Conformance w/ $STORAGE_DRIVER'
alias: conformance
only_if: *not_docs
- depends_on:
- - unit
+ depends_on: *smoke_vendor_cross
gce_instance:
image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
@@ -174,36 +195,11 @@ conformance_task:
conformance_test_script: '${SCRIPT_BASE}/test.sh conformance |& ${_TIMESTAMP}'
-# Confirm cross-compile ALL architectures on a Mac OS-X VM.
-cross_build_task:
- name: "Cross Compile"
- alias: cross_build
- only_if: *not_docs
- depends_on:
- - unit
-
- osx_instance:
- image: 'big-sur-base'
-
- script:
- - brew update
- - brew install go
- - brew install go-md2man
- - brew install gpgme
- - go version
- - make cross CGO_ENABLED=0
-
- binary_artifacts:
- path: ./bin/*
-
-
integration_task:
name: "Integration $DISTRO_NV w/ $STORAGE_DRIVER"
alias: integration
only_if: *not_docs
- depends_on:
- - smoke
- - vendor
+ depends_on: *smoke_vendor_cross
matrix:
# VFS
@@ -259,9 +255,7 @@ in_podman_task:
name: "Containerized Integration"
alias: in_podman
only_if: *not_docs
- depends_on:
- - smoke
- - vendor
+ depends_on: *smoke_vendor_cross
env:
# This is key, cause the scripts to re-execute themselves inside a container.
diff --git a/vendor/github.com/containers/buildah/.gitignore b/vendor/github.com/containers/buildah/.gitignore
index 55bf4069c..939ce6ef5 100644
--- a/vendor/github.com/containers/buildah/.gitignore
+++ b/vendor/github.com/containers/buildah/.gitignore
@@ -4,9 +4,9 @@ docs/*.5
/buildah
/imgtype
/build/
-tests/tools/build
+/tests/tools/build
Dockerfile*
!/tests/bud/*/Dockerfile*
!/tests/conformance/**/Dockerfile*
*.swp
-result
+/result/
diff --git a/vendor/github.com/containers/buildah/.golangci.yml b/vendor/github.com/containers/buildah/.golangci.yml
index 0c7e31007..af0b10c76 100644
--- a/vendor/github.com/containers/buildah/.golangci.yml
+++ b/vendor/github.com/containers/buildah/.golangci.yml
@@ -7,18 +7,7 @@ run:
# Don't exceed number of threads available when running under CI
concurrency: 4
linters:
- enable-all: true
- disable:
- # All these break for one reason or another
- - dupl
- - funlen
- - gochecknoglobals
- - gochecknoinits
- - goconst
- - gocritic
- - gocyclo
- - gosec
- - lll
- - maligned
- - prealloc
- - scopelint
+ enable:
+ - revive
+ - unconvert
+ - unparam
diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md
index 1864a4564..469031925 100644
--- a/vendor/github.com/containers/buildah/CHANGELOG.md
+++ b/vendor/github.com/containers/buildah/CHANGELOG.md
@@ -2,6 +2,178 @@
# Changelog
+## v1.24.1 (2022-02-03)
+
+ executor: Add support for inline --platform within Dockerfile
+ caps: fix buildah run --cap-add=all
+ Update vendor of openshift/imagebuilder
+ Bump version of containers/image and containers/common
+ Update vendor of containers/common
+ System tests: fix accidental vandalism of source dir
+ build(deps): bump github.com/containers/storage from 1.38.1 to 1.38.2
+ imagebuildah.BuildDockerfiles(): create the jobs semaphore
+ build(deps): bump github.com/onsi/gomega from 1.18.0 to 1.18.1
+ overlay: always honor mountProgram
+ overlay: move mount program invocation to separate function
+ overlay: move mount program lookup to separate function
+ Bump to v1.25.0-dev [NO TESTS NEEDED]
+
+## v1.24.0 (2022-01-26)
+
+ Update vendor of containers/common
+ build(deps): bump github.com/golangci/golangci-lint in /tests/tools
+ Github-workflow: Report both failures and errors.
+ build(deps): bump github.com/containers/image/v5 from 5.18.0 to 5.19.0
+ Update docs/buildah-build.1.md
+ [CI:DOCS] Fix typos and improve language
+ buildah bud --network add support for custom networks
+ Make pull commands be consistent
+ docs/buildah-build.1.md: don't imply that -v isn't just a RUN thing
+ build(deps): bump github.com/onsi/gomega from 1.17.0 to 1.18.0
+ Vendor in latest containers/image
+ Run codespell on code
+ .github/dependabot.yml: add tests/tools go.mod
+ CI: rm git-validation, add GHA job to validate PRs
+ tests/tools: bump go-md2man to v2.0.1
+ tests/tools/Makefile: simplify
+ tests/tools: bump onsi/ginkgo to v1.16.5
+ vendor: bump c/common and others
+ mount: add support for custom upper and workdir with overlay mounts
+ linux: fix lookup for runtime
+ overlay: add MountWithOptions to API which extends support for advanced overlay
+ Allow processing of SystemContext from FlagSet
+ .golangci.yml: enable unparam linter
+ util/resolveName: rm bool return
+ tests/tools: bump golangci-lint
+ .gitignore: fixups
+ all: fix capabilities.NewPid deprecation warnings
+ bind/mount.go: fix linter comment
+ all: fix gosimple warning S1039
+ tests/e2e/buildah_suite_test.go: fix gosimple warnings
+ imagebuildah/executor.go: fix gosimple warning
+ util.go: fix gosimple warning
+ build(deps): bump github.com/opencontainers/runc from 1.0.3 to 1.1.0
+ Enable git-daemon tests
+ Allow processing of id options from FlagSet
+ Cirrus: Re-order tasks for more parallelism
+ Cirrus: Freshen VM images
+ Fix platform handling for empty os/arch values
+ Allow processing of network options from FlagSet
+ Fix permissions on secrets directory
+ Update containers/image and containers/common
+ bud.bats: use a local git daemon for the git protocol test
+ Allow processing of common options from FlagSet
+ Cirrus: Run int. tests in parallel with unit
+ vendor c/common
+ Fix default CNI paths
+ build(deps): bump github.com/fsouza/go-dockerclient from 1.7.6 to 1.7.7
+ multi-stage: enable mounting stages across each other with selinux enabled
+ executor: Share selinux label of first stage with other stages in a build
+ buildkit: add from field to bind and cache mounts so images can be used as source
+ Use config.ProxyEnv from containers/common
+ use libnetwork from c/common for networking
+ setup the netns in the buildah parent process
+ build(deps): bump github.com/containerd/containerd from 1.5.8 to 1.5.9
+ build(deps): bump github.com/fsouza/go-dockerclient from 1.7.4 to 1.7.6
+ build: fix libsubid test
+ Allow callers to replace the ContainerSuffix
+ parse: allow parsing anomaly non-human value for memory control group
+ .cirrus: remove static_build from ci
+ stage_executor: re-use all possible layers from cache for squashed builds
+ build(deps): bump github.com/spf13/cobra from 1.2.1 to 1.3.0
+ Allow rootless buildah to set resource limits on cgroup V2
+ build(deps): bump github.com/docker/docker
+ tests: move buildkit mount tests files from TESTSDIR to TESTDIR before modification
+ build(deps): bump github.com/opencontainers/runc from 1.0.2 to 1.0.3
+ Wire logger through to config
+ copier.Put: check for is-not-a-directory using lstat, not stat
+ Turn on rootless cgroupv2 tests
+ Grab all of the containers.conf settings for namespaces.
+ image: set MediaType in OCI manifests
+ copier: RemoveAll possibly-directories
+ Simple README fix
+ images: accept multiple filter with logical AND
+ build(deps): bump github.com/containernetworking/cni from 0.8.1 to 1.0.1
+ UPdate vendor of container/storage
+ build(deps): bump github.com/onsi/gomega from 1.16.0 to 1.17.0
+ build(deps): bump github.com/containers/image/v5 from 5.16.1 to 5.17.0
+ Make LocalIP public function so Podman can use it
+ Fix UnsetEnv for buildah bud
+ Tests should rely only on static/unchanging images
+ run: ensure that stdio pipes are labeled correctly
+ build(deps): bump github.com/docker/docker
+ Cirrus: Bump up to Fedora 35 & Ubuntu 21.10
+ chroot: don't use the generate default seccomp filter for unit tests
+ build(deps): bump github.com/containerd/containerd from 1.5.7 to 1.5.8
+ ssh-agent: Increase timeout before we explicitly close connection
+ docs/tutorials: update
+ Clarify that manifest defaults to localhost as the registry name
+ "config": remove a stray bit of debug output
+ "commit": fix a flag typo
+ Fix an error message: unlocking vs locking
+ Expand the godoc for CommonBuildOptions.Secrets
+ chroot: accept an "rw" option
+ Add --unsetenv option to buildah commit and build
+ define.TempDirForURL(): show CombinedOutput when a command fails
+ config: support the variant field
+ rootless: do not bind mount /sys if not needed
+ Fix tutorial to specify command on buildah run line
+ build: history should not contain ARG values
+ docs: Use guaranteed path for go-md2man
+ run: honor --network=none from builder if nothing specified
+ networkpolicy: Should be enabled instead of default when explictly set
+ Add support for env var secret sources
+ build(deps): bump github.com/docker/docker
+ fix: another non-portable shebang
+ Rootless containers users should use additional groups
+ Support overlayfs path contains colon
+ Report ignorefile location when no content added
+ Add support for host.containers.internal in the /etc/hosts
+ build(deps): bump github.com/onsi/ginkgo from 1.16.4 to 1.16.5
+ imagebuildah: fix nil deref
+ buildkit: add support for mount=type=cache
+ Default secret mode to 400
+ [CI:DOCS] Include manifest example usage
+ docs: update buildah-from, buildah-pull 'platform' option compatibility notes
+ docs: update buildah-build 'platform' option compatibility notes
+ De-dockerize the man page as much as possible
+ [CI:DOCS] Touch up Containerfile man page to show ARG can be 1st
+ docs: Fix and Update Containerfile man page with supported mount types
+ mount: add tmpcopyup to tmpfs mount option
+ buildkit: Add support for --mount=type=tmpfs
+ build(deps): bump github.com/opencontainers/selinux from 1.8.5 to 1.9.1
+ Fix command doc links in README.md
+ build(deps): bump github.com/containers/image/v5 from 5.16.0 to 5.16.1
+ build: Add support for buildkit like --mount=type=bind
+ Bump containerd to v1.5.7
+ build(deps): bump github.com/docker/docker
+ tests: stop pulling php, composer
+ Fix .containerignore link file
+ Cirrus: Fix defunct package metadata breaking cache
+ build(deps): bump github.com/containers/storage from 1.36.0 to 1.37.0
+ buildah build: add --all-platforms
+ Add man page for Containerfile and .containerignore
+ Plumb the remote logger throughut Buildah
+ Replace fmt.Sprintf("%d", x) with strconv.Itoa(x)
+ Run: Cleanup run directory after every RUN step
+ build(deps): bump github.com/containers/common from 0.45.0 to 0.46.0
+ Makefile: adjust -ldflags/-gcflags/-gccgoflags depending on the go implementation
+ Makefile: check for `-race` using `-mod=vendor`
+ imagebuildah: fix an attempt to write to a nil map
+ push: support to specify the compression format
+ conformance: allow test cases to specify dockerUseBuildKit
+ build(deps): bump github.com/containers/common from 0.44.1 to 0.45.0
+ build(deps): bump github.com/containers/common from 0.44.0 to 0.44.1
+ unmarshalConvertedConfig(): handle zstd compression
+ tests/copy/copy: wire up compression options
+ Update to github.com/vbauerster/mpb v7.1.5
+ Add flouthoc to OWNERS
+ build: Add additional step nodes when labels are modified
+ Makefile: turn on race detection whenever it's available
+ conformance: add more tests for exclusion short-circuiting
+ Update VM Images + Drop prior-ubuntu testing
+ Bump to v1.24.0-dev
+
## v1.23.0 (2021-09-13)
Vendor in containers/common v0.44.0
diff --git a/vendor/github.com/containers/buildah/Makefile b/vendor/github.com/containers/buildah/Makefile
index 196c60e29..f3d1ee817 100644
--- a/vendor/github.com/containers/buildah/Makefile
+++ b/vendor/github.com/containers/buildah/Makefile
@@ -111,7 +111,6 @@ codespell:
.PHONY: validate
validate: install.tools
./tests/validate/whitespace.sh
- ./tests/validate/git-validation.sh
./hack/xref-helpmsgs-manpages
./tests/validate/pr-should-include-tests
./tests/validate/buildahimages-are-sane
diff --git a/vendor/github.com/containers/buildah/bind/mount.go b/vendor/github.com/containers/buildah/bind/mount.go
index 789233405..0e45d12c2 100644
--- a/vendor/github.com/containers/buildah/bind/mount.go
+++ b/vendor/github.com/containers/buildah/bind/mount.go
@@ -270,7 +270,7 @@ func UnmountMountpoints(mountpoint string, mountpointsToRemove []string) error {
}
return errors.Wrapf(err, "error checking if %q is mounted", mount.Mountpoint)
}
- if uint64(mount.Major) != uint64(st.Dev) || uint64(mount.Minor) != uint64(st.Dev) { // nolint:unconvert (required for some OS/arch combinations)
+ if uint64(mount.Major) != uint64(st.Dev) || uint64(mount.Minor) != uint64(st.Dev) { //nolint:unconvert // (required for some OS/arch combinations)
logrus.Debugf("%q is apparently not really mounted, skipping", mount.Mountpoint)
continue
}
diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt
index 24a101016..6547f70c5 100644
--- a/vendor/github.com/containers/buildah/changelog.txt
+++ b/vendor/github.com/containers/buildah/changelog.txt
@@ -1,3 +1,173 @@
+- Changelog for v1.24.1 (2022-02-03)
+ * executor: Add support for inline --platform within Dockerfile
+ * caps: fix buildah run --cap-add=all
+ * Update vendor of openshift/imagebuilder
+ * Bump version of containers/image and containers/common
+ * Update vendor of containers/common
+ * System tests: fix accidental vandalism of source dir
+ * build(deps): bump github.com/containers/storage from 1.38.1 to 1.38.2
+ * imagebuildah.BuildDockerfiles(): create the jobs semaphore
+ * build(deps): bump github.com/onsi/gomega from 1.18.0 to 1.18.1
+ * overlay: always honor mountProgram
+ * overlay: move mount program invocation to separate function
+ * overlay: move mount program lookup to separate function
+ * Bump to v1.25.0-dev [NO TESTS NEEDED]
+
+- Changelog for v1.24.0 (2022-01-26)
+ * Update vendor of containers/common
+ * build(deps): bump github.com/golangci/golangci-lint in /tests/tools
+ * Github-workflow: Report both failures and errors.
+ * build(deps): bump github.com/containers/image/v5 from 5.18.0 to 5.19.0
+ * Update docs/buildah-build.1.md
+ * [CI:DOCS] Fix typos and improve language
+ * buildah bud --network add support for custom networks
+ * Make pull commands be consistent
+ * docs/buildah-build.1.md: don't imply that -v isn't just a RUN thing
+ * build(deps): bump github.com/onsi/gomega from 1.17.0 to 1.18.0
+ * Vendor in latest containers/image
+ * Run codespell on code
+ * .github/dependabot.yml: add tests/tools go.mod
+ * CI: rm git-validation, add GHA job to validate PRs
+ * tests/tools: bump go-md2man to v2.0.1
+ * tests/tools/Makefile: simplify
+ * tests/tools: bump onsi/ginkgo to v1.16.5
+ * vendor: bump c/common and others
+ * mount: add support for custom upper and workdir with overlay mounts
+ * linux: fix lookup for runtime
+ * overlay: add MountWithOptions to API which extends support for advanced overlay
+ * Allow processing of SystemContext from FlagSet
+ * .golangci.yml: enable unparam linter
+ * util/resolveName: rm bool return
+ * tests/tools: bump golangci-lint
+ * .gitignore: fixups
+ * all: fix capabilities.NewPid deprecation warnings
+ * bind/mount.go: fix linter comment
+ * all: fix gosimple warning S1039
+ * tests/e2e/buildah_suite_test.go: fix gosimple warnings
+ * imagebuildah/executor.go: fix gosimple warning
+ * util.go: fix gosimple warning
+ * build(deps): bump github.com/opencontainers/runc from 1.0.3 to 1.1.0
+ * Enable git-daemon tests
+ * Allow processing of id options from FlagSet
+ * Cirrus: Re-order tasks for more parallelism
+ * Cirrus: Freshen VM images
+ * Fix platform handling for empty os/arch values
+ * Allow processing of network options from FlagSet
+ * Fix permissions on secrets directory
+ * Update containers/image and containers/common
+ * bud.bats: use a local git daemon for the git protocol test
+ * Allow processing of common options from FlagSet
+ * Cirrus: Run int. tests in parallel with unit
+ * vendor c/common
+ * Fix default CNI paths
+ * build(deps): bump github.com/fsouza/go-dockerclient from 1.7.6 to 1.7.7
+ * multi-stage: enable mounting stages across each other with selinux enabled
+ * executor: Share selinux label of first stage with other stages in a build
+ * buildkit: add from field to bind and cache mounts so images can be used as source
+ * Use config.ProxyEnv from containers/common
+ * use libnetwork from c/common for networking
+ * setup the netns in the buildah parent process
+ * build(deps): bump github.com/containerd/containerd from 1.5.8 to 1.5.9
+ * build(deps): bump github.com/fsouza/go-dockerclient from 1.7.4 to 1.7.6
+ * build: fix libsubid test
+ * Allow callers to replace the ContainerSuffix
+ * parse: allow parsing anomaly non-human value for memory control group
+ * .cirrus: remove static_build from ci
+ * stage_executor: re-use all possible layers from cache for squashed builds
+ * build(deps): bump github.com/spf13/cobra from 1.2.1 to 1.3.0
+ * Allow rootless buildah to set resource limits on cgroup V2
+ * build(deps): bump github.com/docker/docker
+ * tests: move buildkit mount tests files from TESTSDIR to TESTDIR before modification
+ * build(deps): bump github.com/opencontainers/runc from 1.0.2 to 1.0.3
+ * Wire logger through to config
+ * copier.Put: check for is-not-a-directory using lstat, not stat
+ * Turn on rootless cgroupv2 tests
+ * Grab all of the containers.conf settings for namespaces.
+ * image: set MediaType in OCI manifests
+ * copier: RemoveAll possibly-directories
+ * Simple README fix
+ * images: accept multiple filter with logical AND
+ * build(deps): bump github.com/containernetworking/cni from 0.8.1 to 1.0.1
+ * UPdate vendor of container/storage
+ * build(deps): bump github.com/onsi/gomega from 1.16.0 to 1.17.0
+ * build(deps): bump github.com/containers/image/v5 from 5.16.1 to 5.17.0
+ * Make LocalIP public function so Podman can use it
+ * Fix UnsetEnv for buildah bud
+ * Tests should rely only on static/unchanging images
+ * run: ensure that stdio pipes are labeled correctly
+ * build(deps): bump github.com/docker/docker
+ * Cirrus: Bump up to Fedora 35 & Ubuntu 21.10
+ * chroot: don't use the generate default seccomp filter for unit tests
+ * build(deps): bump github.com/containerd/containerd from 1.5.7 to 1.5.8
+ * ssh-agent: Increase timeout before we explicitly close connection
+ * docs/tutorials: update
+ * Clarify that manifest defaults to localhost as the registry name
+ * "config": remove a stray bit of debug output
+ * "commit": fix a flag typo
+ * Fix an error message: unlocking vs locking
+ * Expand the godoc for CommonBuildOptions.Secrets
+ * chroot: accept an "rw" option
+ * Add --unsetenv option to buildah commit and build
+ * define.TempDirForURL(): show CombinedOutput when a command fails
+ * config: support the variant field
+ * rootless: do not bind mount /sys if not needed
+ * Fix tutorial to specify command on buildah run line
+ * build: history should not contain ARG values
+ * docs: Use guaranteed path for go-md2man
+ * run: honor --network=none from builder if nothing specified
+ * networkpolicy: Should be enabled instead of default when explictly set
+ * Add support for env var secret sources
+ * build(deps): bump github.com/docker/docker
+ * fix: another non-portable shebang
+ * Rootless containers users should use additional groups
+ * Support overlayfs path contains colon
+ * Report ignorefile location when no content added
+ * Add support for host.containers.internal in the /etc/hosts
+ * build(deps): bump github.com/onsi/ginkgo from 1.16.4 to 1.16.5
+ * imagebuildah: fix nil deref
+ * buildkit: add support for mount=type=cache
+ * Default secret mode to 400
+ * [CI:DOCS] Include manifest example usage
+ * docs: update buildah-from, buildah-pull 'platform' option compatibility notes
+ * docs: update buildah-build 'platform' option compatibility notes
+ * De-dockerize the man page as much as possible
+ * [CI:DOCS] Touch up Containerfile man page to show ARG can be 1st
+ * docs: Fix and Update Containerfile man page with supported mount types
+ * mount: add tmpcopyup to tmpfs mount option
+ * buildkit: Add support for --mount=type=tmpfs
+ * build(deps): bump github.com/opencontainers/selinux from 1.8.5 to 1.9.1
+ * Fix command doc links in README.md
+ * build(deps): bump github.com/containers/image/v5 from 5.16.0 to 5.16.1
+ * build: Add support for buildkit like --mount=type=bind
+ * Bump containerd to v1.5.7
+ * build(deps): bump github.com/docker/docker
+ * tests: stop pulling php, composer
+ * Fix .containerignore link file
+ * Cirrus: Fix defunct package metadata breaking cache
+ * build(deps): bump github.com/containers/storage from 1.36.0 to 1.37.0
+ * buildah build: add --all-platforms
+ * Add man page for Containerfile and .containerignore
+ * Plumb the remote logger throughut Buildah
+ * Replace fmt.Sprintf("%d", x) with strconv.Itoa(x)
+ * Run: Cleanup run directory after every RUN step
+ * build(deps): bump github.com/containers/common from 0.45.0 to 0.46.0
+ * Makefile: adjust -ldflags/-gcflags/-gccgoflags depending on the go implementation
+ * Makefile: check for `-race` using `-mod=vendor`
+ * imagebuildah: fix an attempt to write to a nil map
+ * push: support to specify the compression format
+ * conformance: allow test cases to specify dockerUseBuildKit
+ * build(deps): bump github.com/containers/common from 0.44.1 to 0.45.0
+ * build(deps): bump github.com/containers/common from 0.44.0 to 0.44.1
+ * unmarshalConvertedConfig(): handle zstd compression
+ * tests/copy/copy: wire up compression options
+ * Update to github.com/vbauerster/mpb v7.1.5
+ * Add flouthoc to OWNERS
+ * build: Add additional step nodes when labels are modified
+ * Makefile: turn on race detection whenever it's available
+ * conformance: add more tests for exclusion short-circuiting
+ * Update VM Images + Drop prior-ubuntu testing
+ * Bump to v1.24.0-dev
+
- Changelog for v1.23.0 (2021-09-13)
* Vendor in containers/common v0.44.0
* build(deps): bump github.com/containers/storage from 1.35.0 to 1.36.0
diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go
index cf0d9871a..badb51e34 100644
--- a/vendor/github.com/containers/buildah/chroot/run.go
+++ b/vendor/github.com/containers/buildah/chroot/run.go
@@ -883,11 +883,14 @@ func setApparmorProfile(spec *specs.Spec) error {
// setCapabilities sets capabilities for ourselves, to be more or less inherited by any processes that we'll start.
func setCapabilities(spec *specs.Spec, keepCaps ...string) error {
- currentCaps, err := capability.NewPid(0)
+ currentCaps, err := capability.NewPid2(0)
if err != nil {
return errors.Wrapf(err, "error reading capabilities of current process")
}
- caps, err := capability.NewPid(0)
+ if err := currentCaps.Load(); err != nil {
+ return errors.Wrapf(err, "error loading capabilities")
+ }
+ caps, err := capability.NewPid2(0)
if err != nil {
return errors.Wrapf(err, "error reading capabilities of current process")
}
@@ -899,30 +902,30 @@ func setCapabilities(spec *specs.Spec, keepCaps ...string) error {
capability.AMBIENT: spec.Process.Capabilities.Ambient,
}
knownCaps := capability.List()
- caps.Clear(capability.CAPS | capability.BOUNDS | capability.AMBS)
+ noCap := capability.Cap(-1)
for capType, capList := range capMap {
for _, capToSet := range capList {
- cap := capability.CAP_LAST_CAP
+ cap := noCap
for _, c := range knownCaps {
if strings.EqualFold("CAP_"+c.String(), capToSet) {
cap = c
break
}
}
- if cap == capability.CAP_LAST_CAP {
+ if cap == noCap {
return errors.Errorf("error mapping capability %q to a number", capToSet)
}
caps.Set(capType, cap)
}
for _, capToSet := range keepCaps {
- cap := capability.CAP_LAST_CAP
+ cap := noCap
for _, c := range knownCaps {
if strings.EqualFold("CAP_"+c.String(), capToSet) {
cap = c
break
}
}
- if cap == capability.CAP_LAST_CAP {
+ if cap == noCap {
return errors.Errorf("error mapping capability %q to a number", capToSet)
}
if currentCaps.Get(capType, cap) {
diff --git a/vendor/github.com/containers/buildah/define/types.go b/vendor/github.com/containers/buildah/define/types.go
index 5bbb1bbac..63a5bf2fb 100644
--- a/vendor/github.com/containers/buildah/define/types.go
+++ b/vendor/github.com/containers/buildah/define/types.go
@@ -29,7 +29,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.24.0-dev"
+ Version = "1.24.1"
// DefaultRuntime if containers.conf fails.
DefaultRuntime = "runc"
diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod
index 6dd50e3ae..5a4e22aea 100644
--- a/vendor/github.com/containers/buildah/go.mod
+++ b/vendor/github.com/containers/buildah/go.mod
@@ -5,10 +5,10 @@ go 1.13
require (
github.com/containerd/containerd v1.5.9
github.com/containernetworking/cni v1.0.1
- github.com/containers/common v0.46.1-0.20220110165509-08c2c97e5e25
- github.com/containers/image/v5 v5.18.0
+ github.com/containers/common v0.47.3
+ github.com/containers/image/v5 v5.19.1
github.com/containers/ocicrypt v1.1.2
- github.com/containers/storage v1.37.1-0.20211122164443-82b8f06bfc08
+ github.com/containers/storage v1.38.2
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/docker v20.10.12+incompatible
github.com/docker/go-units v0.4.0
@@ -20,16 +20,16 @@ require (
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
github.com/mattn/go-shellwords v1.0.12
github.com/onsi/ginkgo v1.16.5
- github.com/onsi/gomega v1.17.0
+ github.com/onsi/gomega v1.18.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.3-0.20211202193544-a5463b7f9c84
- github.com/opencontainers/runc v1.0.3
+ github.com/opencontainers/runc v1.1.0
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.10.0
- github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656
+ github.com/openshift/imagebuilder v1.2.2
github.com/pkg/errors v0.9.1
- github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf
+ github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.3.0
github.com/spf13/pflag v1.0.5
@@ -38,9 +38,8 @@ require (
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
- golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b
- k8s.io/klog v1.0.0 // indirect
)
replace github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.4.2
diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum
index 257af4905..df47d2fc3 100644
--- a/vendor/github.com/containers/buildah/go.sum
+++ b/vendor/github.com/containers/buildah/go.sum
@@ -64,8 +64,9 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
+github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
@@ -90,12 +91,15 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
-github.com/Microsoft/hcsshim v0.9.1 h1:VfDCj+QnY19ktX5TsH22JHcjaZ05RWQiwDbOyEg5ziM=
-github.com/Microsoft/hcsshim v0.9.1/go.mod h1:Y/0uV2jUab5kBI7SQgl62at0AVX7uaruzADAVmxm3eM=
+github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY=
+github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
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/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/ProtonMail/go-crypto v0.0.0-20211112122917-428f8eabeeb3/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
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=
@@ -105,12 +109,14 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
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/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -118,6 +124,7 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -131,6 +138,7 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
github.com/blang/semver v3.1.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/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
@@ -148,6 +156,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
@@ -159,6 +168,7 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -193,6 +203,7 @@ github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@@ -240,8 +251,8 @@ github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oM
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
-github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng=
-github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0 h1:t0IW5kOmY7AXDAWRUs2uVzDhijAUOAYVr/dyRhOQvBg=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -266,11 +277,10 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
github.com/containernetworking/plugins v1.0.1 h1:wwCfYbTCj5FC0EJgyzyjTXmqysOiJE9r712Z+2KVZAk=
github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE=
-github.com/containers/common v0.46.1-0.20220110165509-08c2c97e5e25 h1:LwpIG1dHUvMyuarbmR+KMLi4EF3Ca0afNw15KHN3rDM=
-github.com/containers/common v0.46.1-0.20220110165509-08c2c97e5e25/go.mod h1:hXUU9gtA8V9dSLHhizp/k/s0ZXBzrnUSScUfrsw8z2Y=
-github.com/containers/image/v5 v5.17.1-0.20220106205022-73f80d60f0e1/go.mod h1:daAiRXgcGIf/7eD7B2EkuHHw084/8M8Kh35rzOu56y0=
-github.com/containers/image/v5 v5.18.0 h1:YbvpXl5zd6IbZnt4XiOU0+c24xBQAQL9q3/e5kyk19k=
-github.com/containers/image/v5 v5.18.0/go.mod h1:ybujPwS7YEAPhLXJ3vvZGdKftk+sPSvp/djg9qTPvro=
+github.com/containers/common v0.47.3 h1:pRT7gkLrBSQe3075j5hoHYeeKpGTWBJHws+tS5xxfak=
+github.com/containers/common v0.47.3/go.mod h1:/VAV4ibC27Lfyb9cxXM4uTYrJFa/7s+utNB052MJdzY=
+github.com/containers/image/v5 v5.19.1 h1:g4/+XIuh1kRoRn2MfLDhfHhkNOIO9JtqhSyo55tjpfE=
+github.com/containers/image/v5 v5.19.1/go.mod h1:ewoo3u+TpJvGmsz64XgzbyTHwHtM94q7mgK/pX+v2SE=
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 v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
@@ -279,9 +289,8 @@ github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B
github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
-github.com/containers/storage v1.37.1-0.20211119174841-bf170b3ddac0/go.mod h1:XjCNlt5JUUmRuTJXhFxHb9hHGPho7DNg3o4N/14prdQ=
-github.com/containers/storage v1.37.1-0.20211122164443-82b8f06bfc08 h1:KXVX/ZD4h0ysiz/E3oU5HrWnM9WkI6NGgliPC8IxoVk=
-github.com/containers/storage v1.37.1-0.20211122164443-82b8f06bfc08/go.mod h1:hvKpaiPRALDI7oz4Jx+AEch8iS/viRnc22HPilQROWU=
+github.com/containers/storage v1.38.2 h1:8bAIxnVBGKzMw5EWCivVj24bztQT6IkDp4uHiyhnzwE=
+github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZPWprAbAlQWPQ=
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-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
@@ -336,8 +345,9 @@ github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
-github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q=
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
@@ -357,6 +367,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
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/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -372,6 +383,7 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -385,6 +397,12 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/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/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
+github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -496,6 +514,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
@@ -579,8 +598,10 @@ github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5y
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
-github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI=
-github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
+github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
@@ -596,14 +617,17 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
+github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -614,6 +638,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
@@ -622,6 +647,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
+github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -631,6 +657,7 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
+github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@@ -689,14 +716,11 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
-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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/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/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
@@ -716,6 +740,8 @@ github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1ls
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
+github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
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 v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -725,8 +751,9 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
-github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -741,8 +768,9 @@ github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
+github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -757,11 +785,10 @@ github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqi
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
-github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
-github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4=
-github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
+github.com/openshift/imagebuilder v1.2.2 h1:++jWWMkTVJKP2MIjTPaTk2MqwWIOYYlDaQbZyLlLBh0=
+github.com/openshift/imagebuilder v1.2.2/go.mod h1:TRYHe4CH9U6nkDjxjBNM5klrLbJBrRbpJE5SaRwUBsQ=
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/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -781,6 +808,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
+github.com/proglottis/gpgme v0.1.1 h1:72xI0pt/hy7pqsRxk32KExITkXp+RZErRizsA+up/lQ=
+github.com/proglottis/gpgme v0.1.1/go.mod h1:fPbW/EZ0LvwQtH8Hy7eixhp1eF3G39dtx7GUN+0Gmy0=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
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=
@@ -831,9 +860,15 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
+github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf h1:b0+ZBD3rohnkQ4q5duD1+RyTXTg9yk+qTOPMSQtapO0=
-github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -877,6 +912,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/sylabs/release-tools v0.1.0/go.mod h1:pqP/z/11/rYMQ0OM/Nn7TxGijw7KfZwW9UolD/J1TUo=
+github.com/sylabs/sif/v2 v2.3.1 h1:NHoc/rZpnOS05etmT+j8IJOZP2Cc8zHHG8rKSVosvZs=
+github.com/sylabs/sif/v2 v2.3.1/go.mod h1:NnvveH62GiibimL00MrI6YYcZfb7DnZMcRo/40giY+0=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
@@ -897,8 +935,8 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
-github.com/vbauerster/mpb/v7 v7.3.0 h1:WwRtHHT26gjVln0yJypDEEpTWyX9sk4QcUxM6tQjdEc=
-github.com/vbauerster/mpb/v7 v7.3.0/go.mod h1:KERDXx9bfuStUwTH2FbsrJhJhVu1q+xmjjoCZMZrin4=
+github.com/vbauerster/mpb/v7 v7.3.2 h1:tCuxMy8G9cLdjb61b6wO7I1vRT/LyMEzRbr3xCC0JPU=
+github.com/vbauerster/mpb/v7 v7.3.2/go.mod h1:wfxIZcOJq/bG1/lAtfzMXcOiSvbqVi/5GX5WCSi+IsA=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
@@ -911,6 +949,8 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvV
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -959,6 +999,7 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -971,7 +1012,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1058,15 +1102,17 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1184,6 +1230,7 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1195,14 +1242,18 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211001092434-39dca1131b70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1394,7 +1445,6 @@ google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
@@ -1433,7 +1483,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
@@ -1457,8 +1506,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -1473,6 +1523,7 @@ gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w
gopkg.in/square/go-jose.v2 v2.5.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/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
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=
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index cefb1857e..77d8b6d54 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -176,8 +176,17 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options define.B
files = append(files, b.Bytes())
}
- if options.JobSemaphore == nil && options.Jobs != nil && *options.Jobs != 0 {
- options.JobSemaphore = semaphore.NewWeighted(int64(*options.Jobs))
+ if options.JobSemaphore == nil {
+ if options.Jobs != nil {
+ if *options.Jobs < 0 {
+ return "", nil, errors.New("error building: invalid value for jobs. It must be a positive integer")
+ }
+ if *options.Jobs > 0 {
+ options.JobSemaphore = semaphore.NewWeighted(int64(*options.Jobs))
+ }
+ } else {
+ options.JobSemaphore = semaphore.NewWeighted(1)
+ }
}
manifestList := options.Manifest
diff --git a/vendor/github.com/containers/buildah/imagebuildah/executor.go b/vendor/github.com/containers/buildah/imagebuildah/executor.go
index aa33277f3..5183456d0 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/executor.go
@@ -120,7 +120,6 @@ type Executor struct {
terminatedStage map[string]error
stagesLock sync.Mutex
stagesSemaphore *semaphore.Weighted
- jobs int
logRusage bool
rusageLogFile io.Writer
imageInfoLock sync.Mutex
@@ -187,10 +186,6 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
if err != nil {
return nil, err
}
- jobs := 1
- if options.Jobs != nil {
- jobs = *options.Jobs
- }
writer := options.ReportWriter
if options.Quiet {
@@ -270,7 +265,6 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
ociDecryptConfig: options.OciDecryptConfig,
terminatedStage: make(map[string]error),
stagesSemaphore: options.JobSemaphore,
- jobs: jobs,
logRusage: options.LogRusage,
rusageLogFile: rusageLogFile,
imageInfoCache: make(map[string]imageTypeAndHistoryAndDiffIDs),
@@ -304,9 +298,7 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
// and value, or just an argument, since they can be
// separated by either "=" or whitespace.
list := strings.SplitN(arg.Value, "=", 2)
- if _, stillUnused := exec.unusedArgs[list[0]]; stillUnused {
- delete(exec.unusedArgs, list[0])
- }
+ delete(exec.unusedArgs, list[0])
}
}
break
@@ -643,14 +635,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
ch := make(chan Result, len(stages))
if b.stagesSemaphore == nil {
- jobs := int64(b.jobs)
- if jobs < 0 {
- return "", nil, errors.New("error building: invalid value for jobs. It must be a positive integer")
- } else if jobs == 0 {
- jobs = int64(len(stages))
- }
-
- b.stagesSemaphore = semaphore.NewWeighted(jobs)
+ b.stagesSemaphore = semaphore.NewWeighted(int64(len(stages)))
}
var wg sync.WaitGroup
diff --git a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
index 1cae210a4..ac1068fbf 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
@@ -16,6 +16,7 @@ import (
"github.com/containers/buildah/define"
buildahdocker "github.com/containers/buildah/docker"
"github.com/containers/buildah/internal"
+ "github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/pkg/rusage"
"github.com/containers/buildah/util"
cp "github.com/containers/image/v5/copy"
@@ -595,6 +596,22 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo
}
}
+ builderSystemContext := s.executor.systemContext
+ // get platform string from stage
+ if stage.Builder.Platform != "" {
+ os, arch, variant, err := parse.Platform(stage.Builder.Platform)
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to parse platform %q", stage.Builder.Platform)
+ }
+ if arch != "" || variant != "" {
+ builderSystemContext.ArchitectureChoice = arch
+ builderSystemContext.VariantChoice = variant
+ }
+ if os != "" {
+ builderSystemContext.OSChoice = os
+ }
+ }
+
builderOptions := buildah.BuilderOptions{
Args: ib.Args,
FromImage: from,
@@ -604,7 +621,7 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo
BlobDirectory: s.executor.blobDirectory,
SignaturePolicyPath: s.executor.signaturePolicyPath,
ReportWriter: s.executor.reportWriter,
- SystemContext: s.executor.systemContext,
+ SystemContext: builderSystemContext,
Isolation: s.executor.isolation,
NamespaceOptions: s.executor.namespaceOptions,
ConfigureNetwork: s.executor.configureNetwork,
diff --git a/vendor/github.com/containers/buildah/internal/parse/parse.go b/vendor/github.com/containers/buildah/internal/parse/parse.go
index 23e6aa884..8085cd097 100644
--- a/vendor/github.com/containers/buildah/internal/parse/parse.go
+++ b/vendor/github.com/containers/buildah/internal/parse/parse.go
@@ -316,7 +316,7 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
UID: uid,
GID: gid,
}
- //buildkit parity: change uid and gid if specificed otheriwise keep `0`
+ //buildkit parity: change uid and gid if specified otheriwise keep `0`
err = idtools.MkdirAllAndChownNew(newMount.Source, os.FileMode(mode), idPair)
if err != nil {
return newMount, errors.Wrapf(err, "Unable to change uid,gid of cache directory")
diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go
index 704fa8b42..d05fbde7c 100644
--- a/vendor/github.com/containers/buildah/pkg/cli/common.go
+++ b/vendor/github.com/containers/buildah/pkg/cli/common.go
@@ -69,7 +69,7 @@ type BudResults struct {
Manifest string
NoCache bool
Timestamp int64
- Pull bool
+ Pull string
PullAlways bool
PullNever bool
Quiet bool
@@ -171,7 +171,7 @@ func GetNameSpaceFlagsCompletions() commonComp.FlagCompletions {
func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
fs := pflag.FlagSet{}
fs.BoolVar(&flags.ForceRm, "force-rm", false, "Always remove intermediate containers after a build, even if the build is unsuccessful.")
- fs.BoolVar(&flags.Layers, "layers", UseLayers(), fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override."))
+ fs.BoolVar(&flags.Layers, "layers", UseLayers(), "cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override.")
return fs
}
@@ -214,9 +214,16 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
fs.StringVar(&flags.Manifest, "manifest", "", "add the image to the specified manifest list. Creates manifest list if it does not exist")
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.String("os", runtime.GOOS, "set the OS to the provided value instead of the current operating system of the host")
- 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.StringVar(&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, if always, pull the image even if the named image is present in store, if never, only use the image present in store if available")
+ fs.Lookup("pull").NoOptDefVal = "true" //allow `--pull ` to be set to `true` as expected.
fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image even if the named image is present in store")
+ if err := fs.MarkHidden("pull-always"); err != nil {
+ panic(fmt.Sprintf("error marking the pull-always flag as hidden: %v", err))
+ }
fs.BoolVar(&flags.PullNever, "pull-never", false, "do not pull the image, use the image present in store if available")
+ if err := fs.MarkHidden("pull-never"); err != nil {
+ panic(fmt.Sprintf("error marking the pull-never flag as hidden: %v", err))
+ }
fs.BoolVarP(&flags.Quiet, "quiet", "q", false, "refrain from announcing build instructions and image read/write progress")
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/build.go.
@@ -259,6 +266,7 @@ func GetBudFlagsCompletions() commonComp.FlagCompletions {
flagCompletion["logfile"] = commonComp.AutocompleteDefault
flagCompletion["manifest"] = commonComp.AutocompleteDefault
flagCompletion["os"] = commonComp.AutocompleteNone
+ flagCompletion["pull"] = commonComp.AutocompleteDefault
flagCompletion["runtime-flag"] = commonComp.AutocompleteNone
flagCompletion["secret"] = commonComp.AutocompleteNone
flagCompletion["ssh"] = commonComp.AutocompleteNone
diff --git a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
index e292fe353..c325bc5cf 100644
--- a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
+++ b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
@@ -18,6 +18,40 @@ import (
"golang.org/x/sys/unix"
)
+// Options type holds various configuration options for overlay
+// MountWithOptions accepts following type so it is easier to specify
+// more verbose configuration for overlay mount.
+type Options struct {
+ // The Upper directory is normally writable layer in an overlay mount.
+ // Note!! : Following API does not handles escaping or validates correctness of the values
+ // passed to UpperDirOptionFragment instead API will try to pass values as is it
+ // to the `mount` command. It is user's responsibility to make sure they pre-validate
+ // these values. Invalid inputs may lead to undefined behviour.
+ // This is provided as-is, use it if it works for you, we can/will change/break that in the future.
+ // See discussion here for more context: https://github.com/containers/buildah/pull/3715#discussion_r786036959
+ // TODO: Should we address above comment and handle escaping of metacharacters like
+ // `comma`, `backslash` ,`colon` and any other special characters
+ UpperDirOptionFragment string
+ // The Workdir is used to prepare files as they are switched between the layers.
+ // Note!! : Following API does not handles escaping or validates correctness of the values
+ // passed to WorkDirOptionFragment instead API will try to pass values as is it
+ // to the `mount` command. It is user's responsibility to make sure they pre-validate
+ // these values. Invalid inputs may lead to undefined behviour.
+ // This is provided as-is, use it if it works for you, we can/will change/break that in the future.
+ // See discussion here for more context: https://github.com/containers/buildah/pull/3715#discussion_r786036959
+ // TODO: Should we address above comment and handle escaping of metacharacters like
+ // `comma`, `backslash` ,`colon` and any other special characters
+ WorkDirOptionFragment string
+ // Graph options relayed from podman, will be responsible for choosing mount program
+ GraphOpts []string
+ // Mark if following overlay is read only
+ ReadOnly bool
+ // RootUID is not used yet but keeping it here for legacy reasons.
+ RootUID int
+ // RootGID is not used yet but keeping it here for legacy reasons.
+ RootGID int
+}
+
// TempDir generates an overlay Temp directory in the container content
func TempDir(containerDir string, rootUID, rootGID int) (string, error) {
contentDir := filepath.Join(containerDir, "overlay")
@@ -65,7 +99,8 @@ func generateOverlayStructure(containerDir string, rootUID, rootGID int) (string
// from the source system. It then mounts up the source directory on to the
// generated mount point and returns the mount point to the caller.
func Mount(contentDir, source, dest string, rootUID, rootGID int, graphOptions []string) (mount specs.Mount, Err error) {
- return mountHelper(contentDir, source, dest, rootUID, rootGID, graphOptions, false)
+ overlayOpts := Options{GraphOpts: graphOptions, ReadOnly: false, RootUID: rootUID, RootGID: rootGID}
+ return MountWithOptions(contentDir, source, dest, &overlayOpts)
}
// MountReadOnly creates a subdir of the contentDir based on the source directory
@@ -73,16 +108,55 @@ func Mount(contentDir, source, dest string, rootUID, rootGID int, graphOptions [
// generated mount point and returns the mount point to the caller. Note that no
// upper layer will be created rendering it a read-only mount
func MountReadOnly(contentDir, source, dest string, rootUID, rootGID int, graphOptions []string) (mount specs.Mount, Err error) {
- return mountHelper(contentDir, source, dest, rootUID, rootGID, graphOptions, true)
+ overlayOpts := Options{GraphOpts: graphOptions, ReadOnly: true, RootUID: rootUID, RootGID: rootGID}
+ return MountWithOptions(contentDir, source, dest, &overlayOpts)
+}
+
+// findMountProgram finds if any mount program is specified in the graph options.
+func findMountProgram(graphOptions []string) string {
+ mountMap := map[string]bool{
+ ".mount_program": true,
+ "overlay.mount_program": true,
+ "overlay2.mount_program": true,
+ }
+
+ for _, i := range graphOptions {
+ s := strings.SplitN(i, "=", 2)
+ if len(s) != 2 {
+ continue
+ }
+ key := s[0]
+ val := s[1]
+ if mountMap[key] {
+ return val
+ }
+ }
+
+ return ""
+}
+
+// mountWithMountProgram mount an overlay at mergeDir using the specified mount program
+// and overlay options.
+func mountWithMountProgram(mountProgram, overlayOptions, mergeDir string) error {
+ cmd := exec.Command(mountProgram, "-o", overlayOptions, mergeDir)
+
+ if err := cmd.Run(); err != nil {
+ return errors.Wrapf(err, "exec %s", mountProgram)
+ }
+ return nil
}
-// NOTE: rootUID and rootUID are not yet used.
-func mountHelper(contentDir, source, dest string, _, _ int, graphOptions []string, readOnly bool) (mount specs.Mount, Err error) {
+// MountWithOptions creates a subdir of the contentDir based on the source directory
+// from the source system. It then mounts up the source directory on to the
+// generated mount point and returns the mount point to the caller.
+// But allows api to set custom workdir, upperdir and other overlay options
+// Following API is being used by podman at the moment
+func MountWithOptions(contentDir, source, dest string, opts *Options) (mount specs.Mount, Err error) {
mergeDir := filepath.Join(contentDir, "merge")
// Create overlay mount options for rw/ro.
var overlayOptions string
- if readOnly {
+ if opts.ReadOnly {
// Read-only overlay mounts require two lower layer.
lowerTwo := filepath.Join(contentDir, "lower")
if err := os.Mkdir(lowerTwo, 0755); err != nil {
@@ -93,6 +167,12 @@ func mountHelper(contentDir, source, dest string, _, _ int, graphOptions []strin
// Read-write overlay mounts want a lower, upper and a work layer.
workDir := filepath.Join(contentDir, "work")
upperDir := filepath.Join(contentDir, "upper")
+
+ if opts.WorkDirOptionFragment != "" && opts.UpperDirOptionFragment != "" {
+ workDir = opts.WorkDirOptionFragment
+ upperDir = opts.UpperDirOptionFragment
+ }
+
st, err := os.Stat(source)
if err != nil {
return mount, err
@@ -108,41 +188,21 @@ func mountHelper(contentDir, source, dest string, _, _ int, graphOptions []strin
overlayOptions = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s,private", escapeColon(source), upperDir, workDir)
}
- if unshare.IsRootless() {
- mountProgram := ""
-
- mountMap := map[string]bool{
- ".mount_program": true,
- "overlay.mount_program": true,
- "overlay2.mount_program": true,
- }
-
- for _, i := range graphOptions {
- s := strings.SplitN(i, "=", 2)
- if len(s) != 2 {
- continue
- }
- key := s[0]
- val := s[1]
- if mountMap[key] {
- mountProgram = val
- break
- }
+ mountProgram := findMountProgram(opts.GraphOpts)
+ if mountProgram != "" {
+ if err := mountWithMountProgram(mountProgram, overlayOptions, mergeDir); err != nil {
+ return mount, err
}
- if mountProgram != "" {
- cmd := exec.Command(mountProgram, "-o", overlayOptions, mergeDir)
- if err := cmd.Run(); err != nil {
- return mount, errors.Wrapf(err, "exec %s", mountProgram)
- }
+ mount.Source = mergeDir
+ mount.Destination = dest
+ mount.Type = "bind"
+ mount.Options = []string{"bind", "slave"}
+ return mount, nil
+ }
- mount.Source = mergeDir
- mount.Destination = dest
- mount.Type = "bind"
- mount.Options = []string{"bind", "slave"}
- return mount, nil
- }
- /* If a mount_program is not specified, fallback to try mount native overlay. */
+ if unshare.IsRootless() {
+ /* If a mount_program is not specified, fallback to try mounting native overlay. */
overlayOptions = fmt.Sprintf("%s,userxattr", overlayOptions)
}
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go
index fb1aea2ee..b57b36a62 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go
@@ -441,20 +441,26 @@ func validateIPAddress(val string) (string, error) {
// SystemContextFromOptions returns a SystemContext populated with values
// per the input parameters provided by the caller for the use in authentication.
func SystemContextFromOptions(c *cobra.Command) (*types.SystemContext, error) {
- certDir, err := c.Flags().GetString("cert-dir")
+ return SystemContextFromFlagSet(c.Flags(), c.Flag)
+}
+
+// SystemContextFromFlagSet returns a SystemContext populated with values
+// per the input parameters provided by the caller for the use in authentication.
+func SystemContextFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name string) *pflag.Flag) (*types.SystemContext, error) {
+ certDir, err := flags.GetString("cert-dir")
if err != nil {
certDir = ""
}
ctx := &types.SystemContext{
DockerCertPath: certDir,
}
- tlsVerify, err := c.Flags().GetBool("tls-verify")
- if err == nil && c.Flag("tls-verify").Changed {
+ tlsVerify, err := flags.GetBool("tls-verify")
+ if err == nil && findFlagFunc("tls-verify").Changed {
ctx.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!tlsVerify)
ctx.OCIInsecureSkipTLSVerify = !tlsVerify
ctx.DockerDaemonInsecureSkipTLSVerify = !tlsVerify
}
- disableCompression, err := c.Flags().GetBool("disable-compression")
+ disableCompression, err := flags.GetBool("disable-compression")
if err == nil {
if disableCompression {
ctx.OCIAcceptUncompressedLayers = true
@@ -462,59 +468,59 @@ func SystemContextFromOptions(c *cobra.Command) (*types.SystemContext, error) {
ctx.DirForceCompress = true
}
}
- creds, err := c.Flags().GetString("creds")
- if err == nil && c.Flag("creds").Changed {
+ creds, err := flags.GetString("creds")
+ if err == nil && findFlagFunc("creds").Changed {
var err error
ctx.DockerAuthConfig, err = AuthConfig(creds)
if err != nil {
return nil, err
}
}
- sigPolicy, err := c.Flags().GetString("signature-policy")
- if err == nil && c.Flag("signature-policy").Changed {
+ sigPolicy, err := flags.GetString("signature-policy")
+ if err == nil && findFlagFunc("signature-policy").Changed {
ctx.SignaturePolicyPath = sigPolicy
}
- authfile, err := c.Flags().GetString("authfile")
+ authfile, err := flags.GetString("authfile")
if err == nil {
ctx.AuthFilePath = getAuthFile(authfile)
}
- regConf, err := c.Flags().GetString("registries-conf")
- if err == nil && c.Flag("registries-conf").Changed {
+ regConf, err := flags.GetString("registries-conf")
+ if err == nil && findFlagFunc("registries-conf").Changed {
ctx.SystemRegistriesConfPath = regConf
}
- regConfDir, err := c.Flags().GetString("registries-conf-dir")
- if err == nil && c.Flag("registries-conf-dir").Changed {
+ regConfDir, err := flags.GetString("registries-conf-dir")
+ if err == nil && findFlagFunc("registries-conf-dir").Changed {
ctx.RegistriesDirPath = regConfDir
}
- shortNameAliasConf, err := c.Flags().GetString("short-name-alias-conf")
- if err == nil && c.Flag("short-name-alias-conf").Changed {
+ shortNameAliasConf, err := flags.GetString("short-name-alias-conf")
+ if err == nil && findFlagFunc("short-name-alias-conf").Changed {
ctx.UserShortNameAliasConfPath = shortNameAliasConf
}
ctx.DockerRegistryUserAgent = fmt.Sprintf("Buildah/%s", define.Version)
- if c.Flag("os") != nil && c.Flag("os").Changed {
+ if findFlagFunc("os") != nil && findFlagFunc("os").Changed {
var os string
- if os, err = c.Flags().GetString("os"); err != nil {
+ if os, err = flags.GetString("os"); err != nil {
return nil, err
}
ctx.OSChoice = os
}
- if c.Flag("arch") != nil && c.Flag("arch").Changed {
+ if findFlagFunc("arch") != nil && findFlagFunc("arch").Changed {
var arch string
- if arch, err = c.Flags().GetString("arch"); err != nil {
+ if arch, err = flags.GetString("arch"); err != nil {
return nil, err
}
ctx.ArchitectureChoice = arch
}
- if c.Flag("variant") != nil && c.Flag("variant").Changed {
+ if findFlagFunc("variant") != nil && findFlagFunc("variant").Changed {
var variant string
- if variant, err = c.Flags().GetString("variant"); err != nil {
+ if variant, err = flags.GetString("variant"); err != nil {
return nil, err
}
ctx.VariantChoice = variant
}
- if c.Flag("platform") != nil && c.Flag("platform").Changed {
+ if findFlagFunc("platform") != nil && findFlagFunc("platform").Changed {
var specs []string
- if specs, err = c.Flags().GetStringSlice("platform"); err != nil {
+ if specs, err = flags.GetStringSlice("platform"); err != nil {
return nil, err
}
if len(specs) == 0 || specs[0] == "" {
@@ -664,8 +670,13 @@ func AuthConfig(creds string) (*types.DockerAuthConfig, error) {
// IDMappingOptions parses the build options related to user namespaces and ID mapping.
func IDMappingOptions(c *cobra.Command, isolation define.Isolation) (usernsOptions define.NamespaceOptions, idmapOptions *define.IDMappingOptions, err error) {
- user := c.Flag("userns-uid-map-user").Value.String()
- group := c.Flag("userns-gid-map-group").Value.String()
+ return IDMappingOptionsFromFlagSet(c.Flags(), c.PersistentFlags(), c.Flag)
+}
+
+// IDMappingOptionsFromFlagSet parses the build options related to user namespaces and ID mapping.
+func IDMappingOptionsFromFlagSet(flags *pflag.FlagSet, persistentFlags *pflag.FlagSet, findFlagFunc func(name string) *pflag.Flag) (usernsOptions define.NamespaceOptions, idmapOptions *define.IDMappingOptions, err error) {
+ user := findFlagFunc("userns-uid-map-user").Value.String()
+ group := findFlagFunc("userns-gid-map-group").Value.String()
// If only the user or group was specified, use the same value for the
// other, since we need both in order to initialize the maps using the
// names.
@@ -684,7 +695,7 @@ func IDMappingOptions(c *cobra.Command, isolation define.Isolation) (usernsOptio
}
mappings = submappings
}
- globalOptions := c.PersistentFlags()
+ globalOptions := persistentFlags
// We'll parse the UID and GID mapping options the same way.
buildIDMap := func(basemap []idtools.IDMap, option string) ([]specs.LinuxIDMapping, error) {
outmap := make([]specs.LinuxIDMapping, 0, len(basemap))
@@ -702,8 +713,8 @@ func IDMappingOptions(c *cobra.Command, isolation define.Isolation) (usernsOptio
if globalOptions.Lookup(option) != nil && globalOptions.Lookup(option).Changed {
spec, _ = globalOptions.GetStringSlice(option)
}
- if c.Flag(option).Changed {
- spec, _ = c.Flags().GetStringSlice(option)
+ if findFlagFunc(option).Changed {
+ spec, _ = flags.GetStringSlice(option)
}
idmap, err := parseIDMap(spec)
if err != nil {
@@ -744,8 +755,8 @@ func IDMappingOptions(c *cobra.Command, isolation define.Isolation) (usernsOptio
}
// If the user specifically requested that we either use or don't use
// user namespaces, override that default.
- if c.Flag("userns").Changed {
- how := c.Flag("userns").Value.String()
+ if findFlagFunc("userns").Changed {
+ how := findFlagFunc("userns").Value.String()
switch how {
case "", "container", "private":
usernsOption.Host = false
@@ -814,8 +825,6 @@ func NamespaceOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name st
if flags.Lookup(what) != nil && findFlagFunc(what).Changed {
how := findFlagFunc(what).Value.String()
switch what {
- case "network":
- what = string(specs.NetworkNamespace)
case "cgroupns":
what = string(specs.CgroupNamespace)
}
@@ -845,8 +854,11 @@ func NamespaceOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name st
}
}
how = strings.TrimPrefix(how, "ns:")
- if _, err := os.Stat(how); err != nil {
- return nil, define.NetworkDefault, errors.Wrapf(err, "checking %s namespace", what)
+ // if not a path we assume it is a comma separated network list, see setupNamespaces() in run_linux.go
+ if filepath.IsAbs(how) || what != string(specs.NetworkNamespace) {
+ if _, err := os.Stat(how); err != nil {
+ return nil, define.NetworkDefault, errors.Wrapf(err, "checking %s namespace", what)
+ }
}
policy = define.NetworkEnabled
logrus.Debugf("setting %q namespace to %q", what, how)
diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go
index 0ca720470..f26f4e867 100644
--- a/vendor/github.com/containers/buildah/run_linux.go
+++ b/vendor/github.com/containers/buildah/run_linux.go
@@ -165,6 +165,11 @@ func (b *Builder) Run(command []string, options RunOptions) error {
return err
}
+ // rootless and networks are not supported
+ if len(configureNetworks) > 0 && isolation == IsolationOCIRootless {
+ return errors.New("cannot use networks as rootless")
+ }
+
homeDir, err := b.configureUIDGID(g, mountPoint, options)
if err != nil {
return err
@@ -800,11 +805,10 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, moreCreateArgs [
runtime := options.Runtime
if runtime == "" {
runtime = util.Runtime()
-
- localRuntime := util.FindLocalRuntime(runtime)
- if localRuntime != "" {
- runtime = localRuntime
- }
+ }
+ localRuntime := util.FindLocalRuntime(runtime)
+ if localRuntime != "" {
+ runtime = localRuntime
}
// Default to just passing down our stdio.
@@ -1687,7 +1691,7 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions
namespaceOptions.AddOrReplace(options.NamespaceOptions...)
networkPolicy := options.ConfigureNetwork
- //Nothing was specified explictily so network policy should be inherited from builder
+ //Nothing was specified explicitly so network policy should be inherited from builder
if networkPolicy == NetworkDefault {
networkPolicy = b.ConfigureNetwork
@@ -1788,7 +1792,7 @@ func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string,
parseMount := func(mountType, host, container string, options []string) (specs.Mount, error) {
var foundrw, foundro, foundz, foundZ, foundO, foundU bool
- var rootProp string
+ var rootProp, upperDir, workDir string
for _, opt := range options {
switch opt {
case "rw":
@@ -1806,6 +1810,19 @@ func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string,
case "private", "rprivate", "slave", "rslave", "shared", "rshared":
rootProp = opt
}
+
+ if strings.HasPrefix(opt, "upperdir") {
+ splitOpt := strings.SplitN(opt, "=", 2)
+ if len(splitOpt) > 1 {
+ upperDir = splitOpt[1]
+ }
+ }
+ if strings.HasPrefix(opt, "workdir") {
+ splitOpt := strings.SplitN(opt, "=", 2)
+ if len(splitOpt) > 1 {
+ workDir = splitOpt[1]
+ }
+ }
}
if !foundrw && !foundro {
options = append(options, "rw")
@@ -1826,6 +1843,10 @@ func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string,
}
}
if foundO {
+ if (upperDir != "" && workDir == "") || (workDir != "" && upperDir == "") {
+ return specs.Mount{}, errors.New("if specifying upperdir then workdir must be specified or vice versa")
+ }
+
containerDir, err := b.store.ContainerDirectory(b.ContainerID)
if err != nil {
return specs.Mount{}, err
@@ -1836,7 +1857,14 @@ func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string,
return specs.Mount{}, errors.Wrapf(err, "failed to create TempDir in the %s directory", containerDir)
}
- overlayMount, err := overlay.Mount(contentDir, host, container, rootUID, rootGID, b.store.GraphOptions())
+ overlayOpts := overlay.Options{RootUID: rootUID,
+ RootGID: rootGID,
+ UpperDirOptionFragment: upperDir,
+ WorkDirOptionFragment: workDir,
+ GraphOpts: b.store.GraphOptions(),
+ }
+
+ overlayMount, err := overlay.MountWithOptions(contentDir, host, container, &overlayOpts)
if err == nil {
b.TempVolumes[contentDir] = true
}
@@ -2321,8 +2349,7 @@ func checkAndOverrideIsolationOptions(isolation define.Isolation, options *RunOp
if ns := options.NamespaceOptions.Find(string(specs.NetworkNamespace)); ns != nil {
hostNetworking = ns.Host
networkNamespacePath = ns.Path
- if !hostNetworking && networkNamespacePath != "" && !filepath.IsAbs(networkNamespacePath) {
- logrus.Debugf("Disabling network namespace configuration.")
+ if hostNetworking {
networkNamespacePath = ""
}
}
@@ -2700,7 +2727,6 @@ func (b *Builder) getSSHMount(tokens []string, count int, sshsources map[string]
gid = uint32(gid64)
default:
return nil, nil, errInvalidSyntax
-
}
}
diff --git a/vendor/github.com/containers/buildah/util.go b/vendor/github.com/containers/buildah/util.go
index 47c9ac5cd..9bfa9d268 100644
--- a/vendor/github.com/containers/buildah/util.go
+++ b/vendor/github.com/containers/buildah/util.go
@@ -123,8 +123,8 @@ func isRegistryBlocked(registry string, sc *types.SystemContext) (bool, error) {
// isReferenceSomething checks if the registry part of a reference is insecure or blocked
func isReferenceSomething(ref types.ImageReference, sc *types.SystemContext, what func(string, *types.SystemContext) (bool, error)) (bool, error) {
- if ref != nil && ref.DockerReference() != nil {
- if named, ok := ref.DockerReference().(reference.Named); ok {
+ if ref != nil {
+ if named := ref.DockerReference(); named != nil {
if domain := reference.Domain(named); domain != "" {
return what(domain, sc)
}
diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go
index 7024a821f..13c602c00 100644
--- a/vendor/github.com/containers/buildah/util/util.go
+++ b/vendor/github.com/containers/buildah/util/util.go
@@ -17,7 +17,6 @@ import (
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/pkg/shortnames"
- "github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/image/v5/signature"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
@@ -48,9 +47,8 @@ var (
// resolveName checks if name is a valid image name, and if that name doesn't
// include a domain portion, returns a list of the names which it might
-// correspond to in the set of configured registries, the transport used to
-// pull the image, and a boolean which is true iff
-// 1) the list of search registries was used, and 2) it was empty.
+// correspond to in the set of configured registries, and the transport used to
+// pull the image.
//
// The returned image names never include a transport: prefix, and if transport != "",
// (transport, image) should be a valid input to alltransports.ParseImageName.
@@ -59,9 +57,9 @@ var (
//
// NOTE: The "list of search registries is empty" check does not count blocked registries,
// and neither the implied "localhost" nor a possible firstRegistry are counted
-func resolveName(name string, sc *types.SystemContext, store storage.Store) ([]string, string, bool, error) {
+func resolveName(name string, sc *types.SystemContext, store storage.Store) ([]string, string, error) {
if name == "" {
- return nil, "", false, nil
+ return nil, "", nil
}
// Maybe it's a truncated image ID. Don't prepend a registry name, then.
@@ -69,7 +67,7 @@ func resolveName(name string, sc *types.SystemContext, store storage.Store) ([]s
if img, err := store.Image(name); err == nil && img != nil && strings.HasPrefix(img.ID, name) {
// It's a truncated version of the ID of an image that's present in local storage;
// we need only expand the ID.
- return []string{img.ID}, "", false, nil
+ return []string{img.ID}, "", nil
}
}
// If we're referring to an image by digest, it *must* be local and we
@@ -77,51 +75,32 @@ func resolveName(name string, sc *types.SystemContext, store storage.Store) ([]s
if strings.HasPrefix(name, "sha256:") {
d, err := digest.Parse(name)
if err != nil {
- return nil, "", false, err
+ return nil, "", err
}
img, err := store.Image(d.Encoded())
if err != nil {
- return nil, "", false, err
+ return nil, "", err
}
- return []string{img.ID}, "", false, nil
+ return []string{img.ID}, "", nil
}
// Transports are not supported for local image look ups.
srcRef, err := alltransports.ParseImageName(name)
if err == nil {
- return []string{srcRef.StringWithinTransport()}, srcRef.Transport().Name(), false, nil
+ return []string{srcRef.StringWithinTransport()}, srcRef.Transport().Name(), nil
}
- // Figure out the list of registries.
- var registries []string
- searchRegistries, err := sysregistriesv2.UnqualifiedSearchRegistries(sc)
- if err != nil {
- logrus.Debugf("unable to read configured registries to complete %q: %v", name, err)
- searchRegistries = nil
- }
- for _, registry := range searchRegistries {
- reg, err := sysregistriesv2.FindRegistry(sc, registry)
- if err != nil {
- logrus.Debugf("unable to read registry configuration for %#v: %v", registry, err)
- continue
- }
- if reg == nil || !reg.Blocked {
- registries = append(registries, registry)
- }
- }
- searchRegistriesAreEmpty := len(registries) == 0
-
var candidates []string
// Local short-name resolution.
namedCandidates, err := shortnames.ResolveLocally(sc, name)
if err != nil {
- return nil, "", false, err
+ return nil, "", err
}
for _, named := range namedCandidates {
candidates = append(candidates, named.String())
}
- return candidates, DefaultTransport, searchRegistriesAreEmpty, nil
+ return candidates, DefaultTransport, nil
}
// ExpandNames takes unqualified names, parses them as image names, and returns
@@ -132,7 +111,7 @@ func ExpandNames(names []string, systemContext *types.SystemContext, store stora
expanded := make([]string, 0, len(names))
for _, n := range names {
var name reference.Named
- nameList, _, _, err := resolveName(n, systemContext, store)
+ nameList, _, err := resolveName(n, systemContext, store)
if err != nil {
return nil, errors.Wrapf(err, "error parsing name %q", n)
}
@@ -183,7 +162,7 @@ func ResolveNameToReferences(
systemContext *types.SystemContext,
image string,
) (refs []types.ImageReference, err error) {
- names, transport, _, err := resolveName(image, systemContext, store)
+ names, transport, err := resolveName(image, systemContext, store)
if err != nil {
return nil, errors.Wrapf(err, "error parsing name %q", image)
}
diff --git a/vendor/github.com/containers/common/libnetwork/cni/config.go b/vendor/github.com/containers/common/libnetwork/cni/config.go
index e34daa3c5..b0aa19d94 100644
--- a/vendor/github.com/containers/common/libnetwork/cni/config.go
+++ b/vendor/github.com/containers/common/libnetwork/cni/config.go
@@ -60,7 +60,7 @@ func (n *cniNetwork) networkCreate(newNetwork *types.Network, defaultNet bool) (
// Therefore the next podman command tries to create the default net again and it would
// fail because it thinks the network is used on the host.
var usedNetworks []*net.IPNet
- if !defaultNet {
+ if !defaultNet && newNetwork.Driver == types.BridgeNetworkDriver {
usedNetworks, err = internalutil.GetUsedSubnets(n)
if err != nil {
return nil, err
diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go
index 6d2daf299..7de59f807 100644
--- a/vendor/github.com/containers/common/libnetwork/netavark/config.go
+++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go
@@ -74,7 +74,7 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
// Therefore the next podman command tries to create the default net again and it would
// fail because it thinks the network is used on the host.
var usedNetworks []*net.IPNet
- if !defaultNet {
+ if !defaultNet && newNetwork.Driver == types.BridgeNetworkDriver {
usedNetworks, err = internalutil.GetUsedSubnets(n)
if err != nil {
return nil, err
diff --git a/vendor/github.com/containers/common/libnetwork/netavark/exec.go b/vendor/github.com/containers/common/libnetwork/netavark/exec.go
index 69466a423..1812b9084 100644
--- a/vendor/github.com/containers/common/libnetwork/netavark/exec.go
+++ b/vendor/github.com/containers/common/libnetwork/netavark/exec.go
@@ -107,7 +107,7 @@ func (n *netavarkNetwork) execNetavark(args []string, stdin, result interface{})
logWriter = io.MultiWriter(logWriter, &logrusNetavarkWriter{})
}
- cmd := exec.Command(n.netavarkBinary, args...)
+ cmd := exec.Command(n.netavarkBinary, append(n.getCommonNetavarkOptions(), args...)...)
// connect the pipes to stdin and stdout
cmd.Stdin = stdinR
cmd.Stdout = stdoutW
diff --git a/vendor/github.com/containers/common/libnetwork/netavark/network.go b/vendor/github.com/containers/common/libnetwork/netavark/network.go
index ce252bc1d..7122acf98 100644
--- a/vendor/github.com/containers/common/libnetwork/netavark/network.go
+++ b/vendor/github.com/containers/common/libnetwork/netavark/network.go
@@ -13,6 +13,7 @@ import (
"github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types"
"github.com/containers/storage/pkg/lockfile"
+ "github.com/containers/storage/pkg/unshare"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -21,8 +22,16 @@ type netavarkNetwork struct {
// networkConfigDir is directory where the network config files are stored.
networkConfigDir string
+ // networkRunDir is where temporary files are stored, i.e.the ipam db, aardvark config etc
+ networkRunDir string
+
+ // tells netavark whether this is rootless mode or rootfull, "true" or "false"
+ networkRootless bool
+
// netavarkBinary is the path to the netavark binary.
netavarkBinary string
+ // aardvarkBinary is the path to the aardvark binary.
+ aardvarkBinary string
// defaultNetwork is the name for the default network.
defaultNetwork string
@@ -52,8 +61,10 @@ type InitConfig struct {
// NetavarkBinary is the path to the netavark binary.
NetavarkBinary string
+ // AardvarkBinary is the path to the aardvark binary.
+ AardvarkBinary string
- // NetworkRunDir is where temporary files are stored, i.e.the ipam db.
+ // NetworkRunDir is where temporary files are stored, i.e.the ipam db, aardvark config
NetworkRunDir string
// DefaultNetwork is the name for the default network.
@@ -99,7 +110,10 @@ func NewNetworkInterface(conf *InitConfig) (types.ContainerNetwork, error) {
n := &netavarkNetwork{
networkConfigDir: conf.NetworkConfigDir,
+ networkRunDir: conf.NetworkRunDir,
netavarkBinary: conf.NetavarkBinary,
+ aardvarkBinary: conf.AardvarkBinary,
+ networkRootless: unshare.IsRootless(),
ipamDBPath: filepath.Join(conf.NetworkRunDir, "ipam.db"),
defaultNetwork: defaultNetworkName,
defaultSubnet: defaultNet,
diff --git a/vendor/github.com/containers/common/libnetwork/netavark/run.go b/vendor/github.com/containers/common/libnetwork/netavark/run.go
index c6f2007e2..0a9dc3704 100644
--- a/vendor/github.com/containers/common/libnetwork/netavark/run.go
+++ b/vendor/github.com/containers/common/libnetwork/netavark/run.go
@@ -5,6 +5,7 @@ package netavark
import (
"encoding/json"
"fmt"
+ "strconv"
"github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types"
@@ -110,6 +111,10 @@ func (n *netavarkNetwork) Teardown(namespacePath string, options types.TeardownO
return retErr
}
+func (n *netavarkNetwork) getCommonNetavarkOptions() []string {
+ return []string{"--config", n.networkRunDir, "--rootless=" + strconv.FormatBool(n.networkRootless), "--aardvark-binary=" + n.aardvarkBinary}
+}
+
func (n *netavarkNetwork) convertNetOpts(opts types.NetworkOptions) (*netavarkOptions, error) {
netavarkOptions := netavarkOptions{
NetworkOptions: opts,
diff --git a/vendor/github.com/containers/common/libnetwork/network/interface.go b/vendor/github.com/containers/common/libnetwork/network/interface.go
index 37a910a24..cd4fd89f1 100644
--- a/vendor/github.com/containers/common/libnetwork/network/interface.go
+++ b/vendor/github.com/containers/common/libnetwork/network/interface.go
@@ -31,6 +31,11 @@ const (
netavarkConfigDir = "/etc/containers/networks"
// netavarkRunDir is the run directory for the rootful temporary network files such as the ipam db
netavarkRunDir = "/run/containers/networks"
+
+ // netavarkBinary is the name of the netavark binary
+ netavarkBinary = "netavark"
+ // aardvarkBinary is the name of the aardvark binary
+ aardvarkBinary = "aardvark-dns"
)
// NetworkBackend returns the network backend name and interface
@@ -51,11 +56,17 @@ func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (type
switch backend {
case types.Netavark:
- netavarkBin, err := conf.FindHelperBinary("netavark", false)
+ netavarkBin, err := conf.FindHelperBinary(netavarkBinary, false)
if err != nil {
return "", nil, err
}
+ aardvarkBin, err := conf.FindHelperBinary(aardvarkBinary, false)
+ if err != nil {
+ // this is not a fatal error we can still use netavark without dns
+ logrus.Warnf("%s binary not found, container dns will not be enabled", aardvarkBin)
+ }
+
confDir := conf.Network.NetworkConfigDir
if confDir == "" {
confDir = getDefaultNetavarkConfigDir(store)
@@ -74,6 +85,7 @@ func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (type
NetworkConfigDir: confDir,
NetworkRunDir: runDir,
NetavarkBinary: netavarkBin,
+ AardvarkBinary: aardvarkBin,
DefaultNetwork: conf.Network.DefaultNetwork,
DefaultSubnet: conf.Network.DefaultSubnet,
Syslog: syslog,
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index 6837a378a..dd30abcd6 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -72,6 +72,8 @@ type Config struct {
Network NetworkConfig `toml:"network"`
// Secret section defines configurations for the secret management
Secrets SecretConfig `toml:"secrets"`
+ // ConfigMap section defines configurations for the configmaps management
+ ConfigMaps ConfigMapConfig `toml:"configmaps"`
}
// ContainersConfig represents the "containers" TOML config table
@@ -179,11 +181,6 @@ type ContainersConfig struct {
// performance implications.
PrepareVolumeOnCreate bool `toml:"prepare_volume_on_create,omitempty"`
- // RootlessNetworking depicts the "kind" of networking for rootless
- // containers. Valid options are `slirp4netns` and `cni`. Default is
- // `slirp4netns` on Linux, and `cni` on non-Linux OSes.
- RootlessNetworking string `toml:"rootless_networking,omitempty"`
-
// SeccompProfile is the seccomp.json profile path which is used as the
// default for the runtime.
SeccompProfile string `toml:"seccomp_profile,omitempty"`
@@ -514,6 +511,17 @@ type SecretConfig struct {
Opts map[string]string `toml:"opts,omitempty"`
}
+// ConfigMapConfig represents the "configmap" TOML config table
+type ConfigMapConfig struct {
+ // Driver specifies the configmap driver to use.
+ // Current valid value:
+ // * file
+ // * pass
+ Driver string `toml:"driver,omitempty"`
+ // Opts contains driver specific options
+ Opts map[string]string `toml:"opts,omitempty"`
+}
+
// MachineConfig represents the "machine" TOML config table
type MachineConfig struct {
// Number of CPU's a machine is created with.
@@ -1180,7 +1188,7 @@ func (c *Config) FindHelperBinary(name string, searchPATH bool) (string, error)
return "", errors.Errorf("could not find %q in one of %v. %s", name, c.Engine.HelperBinariesDir, configHint)
}
-// ImageCopyTmpDir default directory to store tempory image files during copy
+// ImageCopyTmpDir default directory to store temporary image files during copy
func (c *Config) ImageCopyTmpDir() (string, error) {
if path, found := os.LookupEnv("TMPDIR"); found {
return path, nil
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index b1e6f5435..f497d2bbe 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -197,10 +197,6 @@ default_sysctls = [
#
#prepare_volume_on_create = false
-# Indicates the networking to be used for rootless containers
-#
-#rootless_networking = "slirp4netns"
-
# Path to the seccomp.json profile which is used as the default seccomp profile
# for the runtime.
#
@@ -403,14 +399,16 @@ default_sysctls = [
# 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.
+# reserving the pods resources for the lifetime of the pod. By default container
+# engines run a builtin container using the pause executable. If you want override
+# specify an image to pull.
#
-#infra_image = "k8s.gcr.io/pause:3.4.1"
+#infra_image = ""
# 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
+# faster "shm" lock type. You may need to run "podman system renumber" after
# you change the lock type.
#
#lock_type** = "shm"
@@ -469,7 +467,7 @@ default_sysctls = [
#
#runtime = "crun"
-# List of the OCI runtimes that support --format=json. When json is supported
+# List of the OCI runtimes that support --format=json. When json is supported
# engine will use it for reporting nicer errors.
#
#runtime_supports_json = ["crun", "runc", "kata", "runsc", "krun"]
@@ -482,8 +480,8 @@ default_sysctls = [
#
#runtime_supports_nocgroups = ["crun", "krun"]
-# Default location for storing temporary container image content. Can be overridden with the TMPDIR environment
-# variable. If you specify "storage", then the location of the
+# Default location for storing temporary container image content. Can be overridden with the TMPDIR environment
+# variable. If you specify "storage", then the location of the
# container/storage tmp directory will be used.
# image_copy_tmp_dir="/var/tmp"
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 55e4e4b67..279119749 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -46,7 +46,7 @@ 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.5"
+ DefaultInfraImage = ""
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
// DefaultDetachKeys is the default keys sequence for detaching a
@@ -177,23 +177,22 @@ func DefaultConfig() (*Config, error) {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
},
- EnvHost: false,
- HTTPProxy: true,
- Init: false,
- InitPath: "",
- IPCNS: "private",
- LogDriver: defaultLogDriver(),
- LogSizeMax: DefaultLogSizeMax,
- NetNS: "private",
- NoHosts: false,
- PidsLimit: DefaultPidsLimit,
- PidNS: "private",
- RootlessNetworking: getDefaultRootlessNetwork(),
- ShmSize: DefaultShmSize,
- TZ: "",
- Umask: "0022",
- UTSNS: "private",
- UserNSSize: DefaultUserNSSize,
+ EnvHost: false,
+ HTTPProxy: true,
+ Init: false,
+ InitPath: "",
+ IPCNS: "private",
+ LogDriver: defaultLogDriver(),
+ LogSizeMax: DefaultLogSizeMax,
+ NetNS: "private",
+ NoHosts: false,
+ PidsLimit: DefaultPidsLimit,
+ PidNS: "private",
+ ShmSize: DefaultShmSize,
+ TZ: "",
+ Umask: "0022",
+ UTSNS: "private",
+ UserNSSize: DefaultUserNSSize,
},
Network: NetworkConfig{
DefaultNetwork: "podman",
@@ -566,9 +565,3 @@ func (c *Config) LogDriver() string {
func (c *Config) MachineEnabled() bool {
return c.Engine.MachineEnabled
}
-
-// RootlessNetworking returns the "kind" of networking
-// rootless containers should use
-func (c *Config) RootlessNetworking() string {
- return c.Containers.RootlessNetworking
-}
diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go
index 9446d3ff9..cc2d0fe3e 100644
--- a/vendor/github.com/containers/common/pkg/config/default_linux.go
+++ b/vendor/github.com/containers/common/pkg/config/default_linux.go
@@ -24,12 +24,6 @@ func getDefaultMachineUser() string {
return "core"
}
-// getDefaultRootlessNetwork returns the default rootless network configuration.
-// It is "slirp4netns" for Linux.
-func getDefaultRootlessNetwork() string {
- return "slirp4netns"
-}
-
// 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
diff --git a/vendor/github.com/containers/common/pkg/config/default_unsupported.go b/vendor/github.com/containers/common/pkg/config/default_unsupported.go
index b6ee286ec..1aa7f6ef3 100644
--- a/vendor/github.com/containers/common/pkg/config/default_unsupported.go
+++ b/vendor/github.com/containers/common/pkg/config/default_unsupported.go
@@ -13,12 +13,6 @@ func getDefaultMachineUser() string {
return "core"
}
-// getDefaultRootlessNetwork returns the default rootless network configuration.
-// It is "cni" for non-Linux OSes (to better support `podman-machine` usecases).
-func getDefaultRootlessNetwork() string {
- return "cni"
-}
-
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
return false, nil
diff --git a/vendor/github.com/containers/common/pkg/config/default_windows.go b/vendor/github.com/containers/common/pkg/config/default_windows.go
index 5f8dd1a28..28f102f1c 100644
--- a/vendor/github.com/containers/common/pkg/config/default_windows.go
+++ b/vendor/github.com/containers/common/pkg/config/default_windows.go
@@ -11,12 +11,6 @@ func getDefaultMachineUser() string {
return "user"
}
-// getDefaultRootlessNetwork returns the default rootless network configuration.
-// It is "cni" for non-Linux OSes (to better support `podman-machine` usecases).
-func getDefaultRootlessNetwork() string {
- return "cni"
-}
-
// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
return false, nil
diff --git a/vendor/github.com/containers/common/pkg/flag/flag.go b/vendor/github.com/containers/common/pkg/flag/flag.go
index 52eb50da0..7d6b6a534 100644
--- a/vendor/github.com/containers/common/pkg/flag/flag.go
+++ b/vendor/github.com/containers/common/pkg/flag/flag.go
@@ -95,7 +95,7 @@ func (os *OptionalString) Value() string {
// newoptionalString
type optionalStringValue OptionalString
-// NewOptionalStringValue returns a pflag.Value fo the string.
+// NewOptionalStringValue returns a pflag.Value for the string.
func NewOptionalStringValue(p *OptionalString) pflag.Value {
p.present = false
return (*optionalStringValue)(p)
diff --git a/vendor/github.com/containers/common/pkg/parse/parse.go b/vendor/github.com/containers/common/pkg/parse/parse.go
index fda129c83..5d826e805 100644
--- a/vendor/github.com/containers/common/pkg/parse/parse.go
+++ b/vendor/github.com/containers/common/pkg/parse/parse.go
@@ -14,9 +14,27 @@ import (
// ValidateVolumeOpts validates a volume's options
func ValidateVolumeOpts(options []string) ([]string, error) {
- var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid, foundChown int
+ var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid, foundChown, foundUpperDir, foundWorkDir int
finalOpts := make([]string, 0, len(options))
for _, opt := range options {
+ // support advanced options like upperdir=/path, workdir=/path
+ if strings.Contains(opt, "upperdir") {
+ foundUpperDir++
+ if foundUpperDir > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 upperdir per overlay", strings.Join(options, ", "))
+ }
+ finalOpts = append(finalOpts, opt)
+ continue
+ }
+ if strings.Contains(opt, "workdir") {
+ foundWorkDir++
+ if foundWorkDir > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 workdir per overlay", strings.Join(options, ", "))
+ }
+ finalOpts = append(finalOpts, opt)
+ continue
+ }
+
switch opt {
case "noexec", "exec":
foundExec++
diff --git a/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go b/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go
index 22aacb1ce..846bd5c17 100644
--- a/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go
+++ b/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go
@@ -36,7 +36,7 @@ type driverConfig struct {
LookupCommand string `mapstructure:"lookup"`
// StoreCommand contains a shell command that stores a secret.
// The secret id is provided as environment variable SECRET_ID
- // The secret value itself is provied over stdin
+ // The secret value itself is provided over stdin
StoreCommand string `mapstructure:"store"`
}
diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
index 6c9321e73..3c0d2b237 100644
--- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
+++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
@@ -149,14 +149,15 @@ func getMountsMap(path string) (string, string, error) { //nolint
// MountsWithUIDGID copies, adds, and mounts the subscriptions to the container root filesystem
// mountLabel: MAC/SELinux label for container content
-// containerWorkingDir: Private data for storing subscriptions on the host mounted in container.
+// containerRunDir: Private data for storing subscriptions on the host mounted in container.
// mountFile: Additional mount points required for the container.
-// mountPoint: Container image mountpoint
+// mountPoint: Container image mountpoint, or the directory from the hosts perspective that
+// corresponds to `/` in the container.
// uid: to assign to content created for subscriptions
// gid: to assign to content created for subscriptions
// rootless: indicates whether container is running in rootless mode
// disableFips: indicates whether system should ignore fips mode
-func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint string, uid, gid int, rootless, disableFips bool) []rspec.Mount {
+func MountsWithUIDGID(mountLabel, containerRunDir, mountFile, mountPoint string, uid, gid int, rootless, disableFips bool) []rspec.Mount {
var (
subscriptionMounts []rspec.Mount
mountFiles []string
@@ -174,7 +175,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
}
for _, file := range mountFiles {
if _, err := os.Stat(file); err == nil {
- mounts, err := addSubscriptionsFromMountsFile(file, mountLabel, containerWorkingDir, uid, gid)
+ mounts, err := addSubscriptionsFromMountsFile(file, mountLabel, containerRunDir, uid, gid)
if err != nil {
logrus.Warnf("Failed to mount subscriptions, skipping entry in %s: %v", file, err)
}
@@ -191,7 +192,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
_, err := os.Stat("/etc/system-fips")
switch {
case err == nil:
- if err := addFIPSModeSubscription(&subscriptionMounts, containerWorkingDir, mountPoint, mountLabel, uid, gid); err != nil {
+ if err := addFIPSModeSubscription(&subscriptionMounts, containerRunDir, mountPoint, mountLabel, uid, gid); err != nil {
logrus.Errorf("Adding FIPS mode subscription to container: %v", err)
}
case os.IsNotExist(err):
@@ -210,7 +211,7 @@ func rchown(chowndir string, uid, gid int) error {
// addSubscriptionsFromMountsFile copies the contents of host directory to container directory
// and returns a list of mounts
-func addSubscriptionsFromMountsFile(filePath, mountLabel, containerWorkingDir string, uid, gid int) ([]rspec.Mount, error) {
+func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string, uid, gid int) ([]rspec.Mount, error) {
var mounts []rspec.Mount
defaultMountsPaths := getMounts(filePath)
for _, path := range defaultMountsPaths {
@@ -228,7 +229,7 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerWorkingDir st
return nil, err
}
- ctrDirOrFileOnHost := filepath.Join(containerWorkingDir, ctrDirOrFile)
+ ctrDirOrFileOnHost := filepath.Join(containerRunDir, ctrDirOrFile)
// In the event of a restart, don't want to copy subscriptions over again as they already would exist in ctrDirOrFileOnHost
_, err = os.Stat(ctrDirOrFileOnHost)
@@ -300,13 +301,17 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerWorkingDir st
return mounts, nil
}
-// addFIPSModeSubscription creates /run/secrets/system-fips in the container
-// root filesystem if /etc/system-fips exists on hosts.
-// This enables the container to be FIPS compliant and run openssl in
-// FIPS mode as the host is also in FIPS mode.
-func addFIPSModeSubscription(mounts *[]rspec.Mount, containerWorkingDir, mountPoint, mountLabel string, uid, gid int) error {
+// addFIPSModeSubscription adds mounts to the `mounts` slice that are needed for the container to run openssl in FIPs mode
+// (i.e: be FIPs compliant).
+// It should only be called if /etc/system-fips exists on host.
+// It primarily does two things:
+// - creates /run/secrets/system-fips in the container root filesystem, and adds it to the `mounts` slice.
+// - If `/etc/crypto-policies/back-ends` already exists inside of the container, it creates
+// `/usr/share/crypto-policies/back-ends/FIPS` inside the container as well.
+// It is done from within the container to ensure to avoid policy incompatibility between the container and host.
+func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, mountLabel string, uid, gid int) error {
subscriptionsDir := "/run/secrets"
- ctrDirOnHost := filepath.Join(containerWorkingDir, subscriptionsDir)
+ ctrDirOnHost := filepath.Join(containerRunDir, subscriptionsDir)
if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) {
if err = idtools.MkdirAllAs(ctrDirOnHost, 0755, uid, gid); err != nil { //nolint
return err
@@ -322,7 +327,7 @@ func addFIPSModeSubscription(mounts *[]rspec.Mount, containerWorkingDir, mountPo
if err != nil {
return errors.Wrap(err, "creating system-fips file in container for FIPS mode")
}
- defer file.Close()
+ file.Close()
}
if !mountExists(*mounts, subscriptionsDir) {
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index b6ceabce5..5ab8cd7f2 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.46.1-dev"
+const Version = "0.47.3"
diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go
index 383215182..512e643b9 100644
--- a/vendor/github.com/containers/image/v5/copy/copy.go
+++ b/vendor/github.com/containers/image/v5/copy/copy.go
@@ -124,6 +124,7 @@ type ImageListSelection int
type Options struct {
RemoveSignatures bool // Remove any pre-existing signatures. SignBy will still add a new signature.
SignBy string // If non-empty, asks for a signature to be added during the copy, and specifies a key ID, as accepted by signature.NewGPGSigningMechanism().SignDockerManifest(),
+ SignPassphrase string // Passphare to use when signing with the key ID from `SignBy`.
ReportWriter io.Writer
SourceCtx *types.SystemContext
DestinationCtx *types.SystemContext
@@ -569,7 +570,7 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
// Sign the manifest list.
if options.SignBy != "" {
- newSig, err := c.createSignature(manifestList, options.SignBy)
+ newSig, err := c.createSignature(manifestList, options.SignBy, options.SignPassphrase)
if err != nil {
return nil, err
}
@@ -791,7 +792,7 @@ func (c *copier) copyOneImage(ctx context.Context, policyContext *signature.Poli
}
if options.SignBy != "" {
- newSig, err := c.createSignature(manifestBytes, options.SignBy)
+ newSig, err := c.createSignature(manifestBytes, options.SignBy, options.SignPassphrase)
if err != nil {
return nil, "", "", err
}
diff --git a/vendor/github.com/containers/image/v5/copy/sign.go b/vendor/github.com/containers/image/v5/copy/sign.go
index 61612a4d3..21a3facd7 100644
--- a/vendor/github.com/containers/image/v5/copy/sign.go
+++ b/vendor/github.com/containers/image/v5/copy/sign.go
@@ -7,7 +7,7 @@ import (
)
// createSignature creates a new signature of manifest using keyIdentity.
-func (c *copier) createSignature(manifest []byte, keyIdentity string) ([]byte, error) {
+func (c *copier) createSignature(manifest []byte, keyIdentity string, passphrase string) ([]byte, error) {
mech, err := signature.NewGPGSigningMechanism()
if err != nil {
return nil, errors.Wrap(err, "initializing GPG")
@@ -23,7 +23,7 @@ func (c *copier) createSignature(manifest []byte, keyIdentity string) ([]byte, e
}
c.Printf("Signing manifest\n")
- newSig, err := signature.SignDockerManifest(manifest, dockerReference.String(), mech, keyIdentity)
+ newSig, err := signature.SignDockerManifestWithOptions(manifest, dockerReference.String(), mech, keyIdentity, &signature.SignOptions{Passphrase: passphrase})
if err != nil {
return nil, errors.Wrap(err, "creating signature")
}
diff --git a/vendor/github.com/containers/image/v5/manifest/common.go b/vendor/github.com/containers/image/v5/manifest/common.go
index 511cdcc37..20955ab7f 100644
--- a/vendor/github.com/containers/image/v5/manifest/common.go
+++ b/vendor/github.com/containers/image/v5/manifest/common.go
@@ -51,7 +51,7 @@ const (
// other than the ones the caller specifically allows.
// expectedMIMEType is used only for diagnostics.
// NOTE: The caller should do the non-heuristic validations (e.g. check for any specified format
-// identification/version, or other “magic numbers”) before calling this, to cleanly reject unambigous
+// identification/version, or other “magic numbers”) before calling this, to cleanly reject unambiguous
// data that just isn’t what was expected, as opposed to actually ambiguous data.
func validateUnambiguousManifestFormat(manifest []byte, expectedMIMEType string,
allowed allowedManifestFields) error {
@@ -71,7 +71,7 @@ func validateUnambiguousManifestFormat(manifest []byte, expectedMIMEType string,
Manifests interface{} `json:"manifests"`
}{}
if err := json.Unmarshal(manifest, &detectedFields); err != nil {
- // The caller was supposed to already validate version numbers, so this shold not happen;
+ // The caller was supposed to already validate version numbers, so this should not happen;
// let’s not bother with making this error “nice”.
return err
}
diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
index 8fa530549..1d73dc405 100644
--- a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
+++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go
@@ -667,6 +667,7 @@ func findCredentialsInFile(key, registry, path string, legacyFormat bool) (types
// This intentionally uses "registry", not "key"; we don't support namespaced
// credentials in helpers.
if ch, exists := auths.CredHelpers[registry]; exists {
+ logrus.Debugf("Looking up in credential helper %s based on credHelpers entry in %s", ch, path)
return getAuthFromCredHelper(ch, registry)
}
@@ -703,6 +704,9 @@ func findCredentialsInFile(key, registry, path string, legacyFormat bool) (types
}
}
+ // Only log this if we found nothing; getCredentialsWithHomeDir logs the
+ // source of found data.
+ logrus.Debugf("No credentials matching %s found in %s", key, path)
return types.DockerAuthConfig{}, nil
}
diff --git a/vendor/github.com/containers/image/v5/sif/load.go b/vendor/github.com/containers/image/v5/sif/load.go
new file mode 100644
index 000000000..ba6d875ba
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/sif/load.go
@@ -0,0 +1,211 @@
+package sif
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/sirupsen/logrus"
+ "github.com/sylabs/sif/v2/pkg/sif"
+)
+
+// injectedScriptTargetPath is the path injectedScript should be written to in the created image.
+const injectedScriptTargetPath = "/podman/runscript"
+
+// parseDefFile parses a SIF definition file from reader,
+// and returns non-trivial contents of the %environment and %runscript sections.
+func parseDefFile(reader io.Reader) ([]string, []string, error) {
+ type parserState int
+ const (
+ parsingOther parserState = iota
+ parsingEnvironment
+ parsingRunscript
+ )
+
+ environment := []string{}
+ runscript := []string{}
+
+ state := parsingOther
+ scanner := bufio.NewScanner(reader)
+ for scanner.Scan() {
+ s := strings.TrimSpace(scanner.Text())
+ switch {
+ case s == `%environment`:
+ state = parsingEnvironment
+ case s == `%runscript`:
+ state = parsingRunscript
+ case strings.HasPrefix(s, "%"):
+ state = parsingOther
+ case state == parsingEnvironment:
+ if s != "" && !strings.HasPrefix(s, "#") {
+ environment = append(environment, s)
+ }
+ case state == parsingRunscript:
+ runscript = append(runscript, s)
+ default: // parsingOther: ignore the line
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, nil, fmt.Errorf("reading lines from SIF definition file object: %w", err)
+ }
+ return environment, runscript, nil
+}
+
+// generateInjectedScript generates a shell script based on
+// SIF definition file %environment and %runscript data, and returns it.
+func generateInjectedScript(environment []string, runscript []string) []byte {
+ script := fmt.Sprintf("#!/bin/bash\n"+
+ "%s\n"+
+ "%s\n", strings.Join(environment, "\n"), strings.Join(runscript, "\n"))
+ return []byte(script)
+}
+
+// processDefFile finds sif.DataDeffile in sifImage, if any,
+// and returns:
+// - the command to run
+// - contents of a script to inject as injectedScriptTargetPath, or nil
+func processDefFile(sifImage *sif.FileImage) (string, []byte, error) {
+ var environment, runscript []string
+
+ desc, err := sifImage.GetDescriptor(sif.WithDataType(sif.DataDeffile))
+ if err == nil {
+ environment, runscript, err = parseDefFile(desc.GetReader())
+ if err != nil {
+ return "", nil, err
+ }
+ }
+
+ var command string
+ var injectedScript []byte
+ if len(environment) == 0 && len(runscript) == 0 {
+ command = "bash"
+ injectedScript = nil
+ } else {
+ injectedScript = generateInjectedScript(environment, runscript)
+ command = injectedScriptTargetPath
+ }
+
+ return command, injectedScript, nil
+}
+
+func writeInjectedScript(extractedRootPath string, injectedScript []byte) error {
+ if injectedScript == nil {
+ return nil
+ }
+ filePath := filepath.Join(extractedRootPath, injectedScriptTargetPath)
+ parentDirPath := filepath.Dir(filePath)
+ if err := os.MkdirAll(parentDirPath, 0755); err != nil {
+ return fmt.Errorf("creating %s: %w", parentDirPath, err)
+ }
+ if err := ioutil.WriteFile(filePath, injectedScript, 0755); err != nil {
+ return fmt.Errorf("writing %s to %s: %w", injectedScriptTargetPath, filePath, err)
+ }
+ return nil
+}
+
+// createTarFromSIFInputs creates a tar file at tarPath, using a squashfs image at squashFSPath.
+// It can also use extractedRootPath and scriptPath, which are allocated for its exclusive use,
+// if necessary.
+func createTarFromSIFInputs(ctx context.Context, tarPath, squashFSPath string, injectedScript []byte, extractedRootPath, scriptPath string) error {
+ // It's safe for the Remove calls to happen even before we create the files, because tempDir is exclusive
+ // for our use.
+ defer os.RemoveAll(extractedRootPath)
+
+ // Almost everything in extractedRootPath comes from squashFSPath.
+ conversionCommand := fmt.Sprintf("unsquashfs -d %s -f %s && tar --acls --xattrs -C %s -cpf %s ./",
+ extractedRootPath, squashFSPath, extractedRootPath, tarPath)
+ script := "#!/bin/sh\n" + conversionCommand + "\n"
+ if err := ioutil.WriteFile(scriptPath, []byte(script), 0755); err != nil {
+ return err
+ }
+ defer os.Remove(scriptPath)
+
+ // On top of squashFSPath, we only add injectedScript, if necessary.
+ if err := writeInjectedScript(extractedRootPath, injectedScript); err != nil {
+ return err
+ }
+
+ logrus.Debugf("Converting squashfs to tar, command: %s ...", conversionCommand)
+ cmd := exec.CommandContext(ctx, "fakeroot", "--", scriptPath)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return fmt.Errorf("converting image: %w, output: %s", err, string(output))
+ }
+ logrus.Debugf("... finished converting squashfs to tar")
+ return nil
+}
+
+// convertSIFToElements processes sifImage and creates/returns
+// the relevant elements for constructing an OCI-like image:
+// - A path to a tar file containing a root filesystem,
+// - A command to run.
+// The returned tar file path is inside tempDir, which can be assumed to be empty
+// at start, and is exclusively used by the current process (i.e. it is safe
+// to use hard-coded relative paths within it).
+func convertSIFToElements(ctx context.Context, sifImage *sif.FileImage, tempDir string) (string, []string, error) {
+ // We could allocate unique names for all of these using ioutil.Temp*, but tempDir is exclusive,
+ // so we can just hard-code a set of unique values here.
+ // We create and/or manage cleanup of these two paths.
+ squashFSPath := filepath.Join(tempDir, "rootfs.squashfs")
+ tarPath := filepath.Join(tempDir, "rootfs.tar")
+ // We only allocate these paths, the user is responsible for cleaning them up.
+ extractedRootPath := filepath.Join(tempDir, "rootfs")
+ scriptPath := filepath.Join(tempDir, "script")
+
+ succeeded := false
+ // It's safe for the Remove calls to happen even before we create the files, because tempDir is exclusive
+ // for our use.
+ // Ideally we would remove squashFSPath immediately after creating extractedRootPath, but we need
+ // to run both creation and consumption of extractedRootPath in the same fakeroot context.
+ // So, overall, this process requires at least 2 compressed copies (SIF and squashFSPath) and 2
+ // uncompressed copies (extractedRootPath and tarPath) of the data, all using up space at the same time.
+ // That's rather unsatisfactory, ideally we would be streaming the data directly from a squashfs parser
+ // reading from the SIF file to a tarball, for 1 compressed and 1 uncompressed copy.
+ defer os.Remove(squashFSPath)
+ defer func() {
+ if !succeeded {
+ os.Remove(tarPath)
+ }
+ }()
+
+ command, injectedScript, err := processDefFile(sifImage)
+ if err != nil {
+ return "", nil, err
+ }
+
+ rootFS, err := sifImage.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys))
+ if err != nil {
+ return "", nil, fmt.Errorf("looking up rootfs from SIF file: %w", err)
+ }
+ // TODO: We'd prefer not to make a full copy of the file here; unsquashfs ≥ 4.4
+ // has an -o option that allows extracting a squashfs from the SIF file directly,
+ // but that version is not currently available in RHEL 8.
+ logrus.Debugf("Creating a temporary squashfs image %s ...", squashFSPath)
+ if err := func() error { // A scope for defer
+ f, err := os.Create(squashFSPath)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
+ if _, err := io.CopyN(f, rootFS.GetReader(), rootFS.Size()); err != nil {
+ return err
+ }
+ return nil
+ }(); err != nil {
+ return "", nil, err
+ }
+ logrus.Debugf("... finished creating a temporary squashfs image")
+
+ if err := createTarFromSIFInputs(ctx, tarPath, squashFSPath, injectedScript, extractedRootPath, scriptPath); err != nil {
+ return "", nil, err
+ }
+ succeeded = true
+ return tarPath, []string{command}, nil
+}
diff --git a/vendor/github.com/containers/image/v5/sif/src.go b/vendor/github.com/containers/image/v5/sif/src.go
new file mode 100644
index 000000000..ba95a469f
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/sif/src.go
@@ -0,0 +1,217 @@
+package sif
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+
+ "github.com/containers/image/v5/internal/tmpdir"
+ "github.com/containers/image/v5/types"
+ "github.com/opencontainers/go-digest"
+ imgspecs "github.com/opencontainers/image-spec/specs-go"
+ imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
+ "github.com/sirupsen/logrus"
+ "github.com/sylabs/sif/v2/pkg/sif"
+)
+
+type sifImageSource struct {
+ ref sifReference
+ workDir string
+ layerDigest digest.Digest
+ layerSize int64
+ layerFile string
+ config []byte
+ configDigest digest.Digest
+ manifest []byte
+}
+
+// getBlobInfo returns the digest, and size of the provided file.
+func getBlobInfo(path string) (digest.Digest, int64, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return "", -1, fmt.Errorf("opening %q for reading: %w", path, err)
+ }
+ defer f.Close()
+
+ // TODO: Instead of writing the tar file to disk, and reading
+ // it here again, stream the tar file to a pipe and
+ // compute the digest while writing it to disk.
+ logrus.Debugf("Computing a digest of the SIF conversion output...")
+ digester := digest.Canonical.Digester()
+ // TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
+ size, err := io.Copy(digester.Hash(), f)
+ if err != nil {
+ return "", -1, fmt.Errorf("reading %q: %w", path, err)
+ }
+ digest := digester.Digest()
+ logrus.Debugf("... finished computing the digest of the SIF conversion output")
+
+ return digest, size, nil
+}
+
+// newImageSource returns an ImageSource for reading from an existing directory.
+// newImageSource extracts SIF objects and saves them in a temp directory.
+func newImageSource(ctx context.Context, sys *types.SystemContext, ref sifReference) (types.ImageSource, error) {
+ sifImg, err := sif.LoadContainerFromPath(ref.file, sif.OptLoadWithFlag(os.O_RDONLY))
+ if err != nil {
+ return nil, fmt.Errorf("loading SIF file: %w", err)
+ }
+ defer func() {
+ _ = sifImg.UnloadContainer()
+ }()
+
+ workDir, err := ioutil.TempDir(tmpdir.TemporaryDirectoryForBigFiles(sys), "sif")
+ if err != nil {
+ return nil, fmt.Errorf("creating temp directory: %w", err)
+ }
+ succeeded := false
+ defer func() {
+ if !succeeded {
+ os.RemoveAll(workDir)
+ }
+ }()
+
+ layerPath, commandLine, err := convertSIFToElements(ctx, sifImg, workDir)
+ if err != nil {
+ return nil, fmt.Errorf("converting rootfs from SquashFS to Tarball: %w", err)
+ }
+
+ layerDigest, layerSize, err := getBlobInfo(layerPath)
+ if err != nil {
+ return nil, fmt.Errorf("gathering blob information: %w", err)
+ }
+
+ created := sifImg.ModifiedAt()
+ config := imgspecv1.Image{
+ Created: &created,
+ Architecture: sifImg.PrimaryArch(),
+ OS: "linux",
+ Config: imgspecv1.ImageConfig{
+ Cmd: commandLine,
+ },
+ RootFS: imgspecv1.RootFS{
+ Type: "layers",
+ DiffIDs: []digest.Digest{layerDigest},
+ },
+ History: []imgspecv1.History{
+ {
+ Created: &created,
+ CreatedBy: fmt.Sprintf("/bin/sh -c #(nop) ADD file:%s in %c", layerDigest.Hex(), os.PathSeparator),
+ Comment: "imported from SIF, uuid: " + sifImg.ID(),
+ },
+ {
+ Created: &created,
+ CreatedBy: "/bin/sh -c #(nop) CMD [\"bash\"]",
+ EmptyLayer: true,
+ },
+ },
+ }
+ configBytes, err := json.Marshal(&config)
+ if err != nil {
+ return nil, fmt.Errorf("generating configuration blob for %q: %w", ref.resolvedFile, err)
+ }
+ configDigest := digest.Canonical.FromBytes(configBytes)
+
+ manifest := imgspecv1.Manifest{
+ Versioned: imgspecs.Versioned{SchemaVersion: 2},
+ MediaType: imgspecv1.MediaTypeImageManifest,
+ Config: imgspecv1.Descriptor{
+ Digest: configDigest,
+ Size: int64(len(configBytes)),
+ MediaType: imgspecv1.MediaTypeImageConfig,
+ },
+ Layers: []imgspecv1.Descriptor{{
+ Digest: layerDigest,
+ Size: layerSize,
+ MediaType: imgspecv1.MediaTypeImageLayer,
+ }},
+ }
+ manifestBytes, err := json.Marshal(&manifest)
+ if err != nil {
+ return nil, fmt.Errorf("generating manifest for %q: %w", ref.resolvedFile, err)
+ }
+
+ succeeded = true
+ return &sifImageSource{
+ ref: ref,
+ workDir: workDir,
+ layerDigest: layerDigest,
+ layerSize: layerSize,
+ layerFile: layerPath,
+ config: configBytes,
+ configDigest: configDigest,
+ manifest: manifestBytes,
+ }, nil
+}
+
+// Reference returns the reference used to set up this source.
+func (s *sifImageSource) Reference() types.ImageReference {
+ return s.ref
+}
+
+// Close removes resources associated with an initialized ImageSource, if any.
+func (s *sifImageSource) Close() error {
+ return os.RemoveAll(s.workDir)
+}
+
+// HasThreadSafeGetBlob indicates whether GetBlob can be executed concurrently.
+func (s *sifImageSource) HasThreadSafeGetBlob() bool {
+ return true
+}
+
+// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
+// The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
+// May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.
+func (s *sifImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
+ switch info.Digest {
+ case s.configDigest:
+ return ioutil.NopCloser(bytes.NewBuffer(s.config)), int64(len(s.config)), nil
+ case s.layerDigest:
+ reader, err := os.Open(s.layerFile)
+ if err != nil {
+ return nil, -1, fmt.Errorf("opening %q: %w", s.layerFile, err)
+ }
+ return reader, s.layerSize, nil
+ default:
+ return nil, -1, fmt.Errorf("no blob with digest %q found", info.Digest.String())
+ }
+}
+
+// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
+// It may use a remote (= slow) service.
+// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
+// this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
+func (s *sifImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
+ if instanceDigest != nil {
+ return nil, "", errors.New("manifest lists are not supported by the sif transport")
+ }
+ return s.manifest, imgspecv1.MediaTypeImageManifest, nil
+}
+
+// GetSignatures returns the image's signatures. It may use a remote (= slow) service.
+// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve signatures for
+// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
+// (e.g. if the source never returns manifest lists).
+func (s *sifImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
+ if instanceDigest != nil {
+ return nil, errors.New("manifest lists are not supported by the sif transport")
+ }
+ return nil, nil
+}
+
+// LayerInfosForCopy returns either nil (meaning the values in the manifest are fine), or updated values for the layer
+// blobsums that are listed in the image's manifest. If values are returned, they should be used when using GetBlob()
+// to read the image's layers.
+// If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve BlobInfos for
+// (when the primary manifest is a manifest list); this never happens if the primary manifest is not a manifest list
+// (e.g. if the source never returns manifest lists).
+// The Digest field is guaranteed to be provided; Size may be -1.
+// WARNING: The list may contain duplicates, and they are semantically relevant.
+func (s *sifImageSource) LayerInfosForCopy(ctx context.Context, instanceDigest *digest.Digest) ([]types.BlobInfo, error) {
+ return nil, nil
+}
diff --git a/vendor/github.com/containers/image/v5/sif/transport.go b/vendor/github.com/containers/image/v5/sif/transport.go
new file mode 100644
index 000000000..18d894bc3
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/sif/transport.go
@@ -0,0 +1,164 @@
+package sif
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/image/v5/directory/explicitfilepath"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/image"
+ "github.com/containers/image/v5/transports"
+ "github.com/containers/image/v5/types"
+)
+
+func init() {
+ transports.Register(Transport)
+}
+
+// Transport is an ImageTransport for SIF images.
+var Transport = sifTransport{}
+
+type sifTransport struct{}
+
+func (t sifTransport) Name() string {
+ return "sif"
+}
+
+// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference.
+func (t sifTransport) ParseReference(reference string) (types.ImageReference, error) {
+ return NewReference(reference)
+}
+
+// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys
+// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value).
+// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion.
+// scope passed to this function will not be "", that value is always allowed.
+func (t sifTransport) ValidatePolicyConfigurationScope(scope string) error {
+ if !strings.HasPrefix(scope, "/") {
+ return fmt.Errorf("Invalid scope %s: Must be an absolute path", scope)
+ }
+ // Refuse also "/", otherwise "/" and "" would have the same semantics,
+ // and "" could be unexpectedly shadowed by the "/" entry.
+ if scope == "/" {
+ return errors.New(`Invalid scope "/": Use the generic default scope ""`)
+ }
+ cleaned := filepath.Clean(scope)
+ if cleaned != scope {
+ return fmt.Errorf(`Invalid scope %s: Uses non-canonical format, perhaps try %s`, scope, cleaned)
+ }
+ return nil
+}
+
+// sifReference is an ImageReference for SIF images.
+type sifReference struct {
+ // Note that the interpretation of paths below depends on the underlying filesystem state, which may change under us at any time!
+ // Either of the paths may point to a different, or no, inode over time. resolvedFile may contain symbolic links, and so on.
+
+ // Generally we follow the intent of the user, and use the "file" member for filesystem operations (e.g. the user can use a relative path to avoid
+ // being exposed to symlinks and renames in the parent directories to the working directory).
+ // (But in general, we make no attempt to be completely safe against concurrent hostile filesystem modifications.)
+ file string // As specified by the user. May be relative, contain symlinks, etc.
+ resolvedFile string // Absolute file path with no symlinks, at least at the time of its creation. Primarily used for policy namespaces.
+}
+
+// There is no sif.ParseReference because it is rather pointless.
+// Callers who need a transport-independent interface will go through
+// sifTransport.ParseReference; callers who intentionally deal with SIF files
+// can use sif.NewReference.
+
+// NewReference returns an image file reference for a specified path.
+func NewReference(file string) (types.ImageReference, error) {
+ // We do not expose an API supplying the resolvedFile; we could, but recomputing it
+ // is generally cheap enough that we prefer being confident about the properties of resolvedFile.
+ resolved, err := explicitfilepath.ResolvePathToFullyExplicit(file)
+ if err != nil {
+ return nil, err
+ }
+ return sifReference{file: file, resolvedFile: resolved}, nil
+}
+
+func (ref sifReference) Transport() types.ImageTransport {
+ return Transport
+}
+
+// StringWithinTransport returns a string representation of the reference, which MUST be such that
+// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference.
+// NOTE: The returned string is not promised to be equal to the original input to ParseReference;
+// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
+// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix;
+// instead, see transports.ImageName().
+func (ref sifReference) StringWithinTransport() string {
+ return ref.file
+}
+
+// DockerReference returns a Docker reference associated with this reference
+// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent,
+// not e.g. after redirect or alias processing), or nil if unknown/not applicable.
+func (ref sifReference) DockerReference() reference.Named {
+ return nil
+}
+
+// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup.
+// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases;
+// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical
+// (i.e. various references with exactly the same semantics should return the same configuration identity)
+// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but
+// not required/guaranteed that it will be a valid input to Transport().ParseReference().
+// Returns "" if configuration identities for these references are not supported.
+func (ref sifReference) PolicyConfigurationIdentity() string {
+ return ref.resolvedFile
+}
+
+// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search
+// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed
+// in order, terminating on first match, and an implicit "" is always checked at the end.
+// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(),
+// and each following element to be a prefix of the element preceding it.
+func (ref sifReference) PolicyConfigurationNamespaces() []string {
+ res := []string{}
+ path := ref.resolvedFile
+ for {
+ lastSlash := strings.LastIndex(path, "/")
+ if lastSlash == -1 || lastSlash == 0 {
+ break
+ }
+ path = path[:lastSlash]
+ res = append(res, path)
+ }
+ // Note that we do not include "/"; it is redundant with the default "" global default,
+ // and rejected by sifTransport.ValidatePolicyConfigurationScope above.
+ return res
+}
+
+// NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport.
+// The caller must call .Close() on the returned ImageCloser.
+// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
+// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
+// WARNING: This may not do the right thing for a manifest list, see image.FromSource for details.
+func (ref sifReference) NewImage(ctx context.Context, sys *types.SystemContext) (types.ImageCloser, error) {
+ src, err := newImageSource(ctx, sys, ref)
+ if err != nil {
+ return nil, err
+ }
+ return image.FromSource(ctx, sys, src)
+}
+
+// NewImageSource returns a types.ImageSource for this reference.
+// The caller must call .Close() on the returned ImageSource.
+func (ref sifReference) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
+ return newImageSource(ctx, sys, ref)
+}
+
+// NewImageDestination returns a types.ImageDestination for this reference.
+// The caller must call .Close() on the returned ImageDestination.
+func (ref sifReference) NewImageDestination(ctx context.Context, sys *types.SystemContext) (types.ImageDestination, error) {
+ return nil, errors.New(`"sif:" locations can only be read from, not written to`)
+}
+
+// DeleteImage deletes the named image from the registry, if supported.
+func (ref sifReference) DeleteImage(ctx context.Context, sys *types.SystemContext) error {
+ return errors.New("Deleting images not implemented for sif: images")
+}
diff --git a/vendor/github.com/containers/image/v5/signature/docker.go b/vendor/github.com/containers/image/v5/signature/docker.go
index 07fdd42a9..8e9ce0dd2 100644
--- a/vendor/github.com/containers/image/v5/signature/docker.go
+++ b/vendor/github.com/containers/image/v5/signature/docker.go
@@ -3,22 +3,46 @@
package signature
import (
+ "errors"
"fmt"
+ "strings"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
"github.com/opencontainers/go-digest"
)
+// SignOptions includes optional parameters for signing container images.
+type SignOptions struct {
+ // Passphare to use when signing with the key identity.
+ Passphrase string
+}
+
// SignDockerManifest returns a signature for manifest as the specified dockerReference,
-// using mech and keyIdentity.
-func SignDockerManifest(m []byte, dockerReference string, mech SigningMechanism, keyIdentity string) ([]byte, error) {
+// using mech and keyIdentity, and the specified options.
+func SignDockerManifestWithOptions(m []byte, dockerReference string, mech SigningMechanism, keyIdentity string, options *SignOptions) ([]byte, error) {
manifestDigest, err := manifest.Digest(m)
if err != nil {
return nil, err
}
sig := newUntrustedSignature(manifestDigest, dockerReference)
- return sig.sign(mech, keyIdentity)
+
+ var passphrase string
+ if options != nil {
+ passphrase = options.Passphrase
+ // The gpgme implementation can’t use passphrase with \n; reject it here for consistent behavior.
+ if strings.Contains(passphrase, "\n") {
+ return nil, errors.New("invalid passphrase: must not contain a line break")
+ }
+ }
+
+ return sig.sign(mech, keyIdentity, passphrase)
+}
+
+// SignDockerManifest returns a signature for manifest as the specified dockerReference,
+// using mech and keyIdentity.
+func SignDockerManifest(m []byte, dockerReference string, mech SigningMechanism, keyIdentity string) ([]byte, error) {
+ return SignDockerManifestWithOptions(m, dockerReference, mech, keyIdentity, nil)
}
// VerifyDockerManifestSignature checks that unverifiedSignature uses expectedKeyIdentity to sign unverifiedManifest as expectedDockerReference,
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism.go b/vendor/github.com/containers/image/v5/signature/mechanism.go
index ee3442cdf..9a32a4364 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism.go
@@ -18,8 +18,6 @@ import (
// SigningMechanism abstracts a way to sign binary blobs and verify their signatures.
// Each mechanism should eventually be closed by calling Close().
-// FIXME: Eventually expand on keyIdentity (namespace them between mechanisms to
-// eliminate ambiguities, support CA signatures and perhaps other key properties)
type SigningMechanism interface {
// Close removes resources associated with the mechanism, if any.
Close() error
@@ -38,6 +36,15 @@ type SigningMechanism interface {
UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error)
}
+// signingMechanismWithPassphrase is an internal extension of SigningMechanism.
+type signingMechanismWithPassphrase interface {
+ SigningMechanism
+
+ // Sign creates a (non-detached) signature of input using keyIdentity and passphrase.
+ // Fails with a SigningNotSupportedError if the mechanism does not support signing.
+ SignWithPassphrase(input []byte, keyIdentity string, passphrase string) ([]byte, error)
+}
+
// SigningNotSupportedError is returned when trying to sign using a mechanism which does not support that.
type SigningNotSupportedError string
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
index 6ae74d430..c166fb32d 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
@@ -5,11 +5,12 @@ package signature
import (
"bytes"
+ "errors"
"fmt"
"io/ioutil"
"os"
- "github.com/mtrmac/gpgme"
+ "github.com/proglottis/gpgme"
)
// A GPG/OpenPGP signing mechanism, implemented using gpgme.
@@ -20,7 +21,7 @@ type gpgmeSigningMechanism struct {
// newGPGSigningMechanismInDirectory returns a new GPG/OpenPGP signing mechanism, using optionalDir if not empty.
// The caller must call .Close() on the returned SigningMechanism.
-func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, error) {
+func newGPGSigningMechanismInDirectory(optionalDir string) (signingMechanismWithPassphrase, error) {
ctx, err := newGPGMEContext(optionalDir)
if err != nil {
return nil, err
@@ -35,7 +36,7 @@ func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, er
// recognizes _only_ public keys from the supplied blob, and returns the identities
// of these keys.
// The caller must call .Close() on the returned SigningMechanism.
-func newEphemeralGPGSigningMechanism(blob []byte) (SigningMechanism, []string, error) {
+func newEphemeralGPGSigningMechanism(blob []byte) (signingMechanismWithPassphrase, []string, error) {
dir, err := ioutil.TempDir("", "containers-ephemeral-gpg-")
if err != nil {
return nil, nil, err
@@ -117,9 +118,9 @@ func (m *gpgmeSigningMechanism) SupportsSigning() error {
return nil
}
-// Sign creates a (non-detached) signature of input using keyIdentity.
+// Sign creates a (non-detached) signature of input using keyIdentity and passphrase.
// Fails with a SigningNotSupportedError if the mechanism does not support signing.
-func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) {
+func (m *gpgmeSigningMechanism) SignWithPassphrase(input []byte, keyIdentity string, passphrase string) ([]byte, error) {
key, err := m.ctx.GetKey(keyIdentity, true)
if err != nil {
return nil, err
@@ -133,12 +134,38 @@ func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte,
if err != nil {
return nil, err
}
+
+ if passphrase != "" {
+ // Callback to write the passphrase to the specified file descriptor.
+ callback := func(uidHint string, prevWasBad bool, gpgmeFD *os.File) error {
+ if prevWasBad {
+ return errors.New("bad passphrase")
+ }
+ _, err := gpgmeFD.WriteString(passphrase + "\n")
+ return err
+ }
+ if err := m.ctx.SetCallback(callback); err != nil {
+ return nil, fmt.Errorf("setting gpgme passphrase callback: %w", err)
+ }
+
+ // Loopback mode will use the callback instead of prompting the user.
+ if err := m.ctx.SetPinEntryMode(gpgme.PinEntryLoopback); err != nil {
+ return nil, fmt.Errorf("setting gpgme pinentry mode: %w", err)
+ }
+ }
+
if err = m.ctx.Sign([]*gpgme.Key{key}, inputData, sigData, gpgme.SigModeNormal); err != nil {
return nil, err
}
return sigBuffer.Bytes(), nil
}
+// Sign creates a (non-detached) signature of input using keyIdentity.
+// Fails with a SigningNotSupportedError if the mechanism does not support signing.
+func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) {
+ return m.SignWithPassphrase(input, keyIdentity, "")
+}
+
// Verify parses unverifiedSignature and returns the content and the signer's identity
func (m *gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
signedBuffer := bytes.Buffer{}
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
index 2f5ebb171..7a31425f1 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
@@ -30,7 +30,7 @@ type openpgpSigningMechanism struct {
// newGPGSigningMechanismInDirectory returns a new GPG/OpenPGP signing mechanism, using optionalDir if not empty.
// The caller must call .Close() on the returned SigningMechanism.
-func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, error) {
+func newGPGSigningMechanismInDirectory(optionalDir string) (signingMechanismWithPassphrase, error) {
m := &openpgpSigningMechanism{
keyring: openpgp.EntityList{},
}
@@ -61,7 +61,7 @@ func newGPGSigningMechanismInDirectory(optionalDir string) (SigningMechanism, er
// recognizes _only_ public keys from the supplied blob, and returns the identities
// of these keys.
// The caller must call .Close() on the returned SigningMechanism.
-func newEphemeralGPGSigningMechanism(blob []byte) (SigningMechanism, []string, error) {
+func newEphemeralGPGSigningMechanism(blob []byte) (signingMechanismWithPassphrase, []string, error) {
m := &openpgpSigningMechanism{
keyring: openpgp.EntityList{},
}
@@ -110,10 +110,16 @@ func (m *openpgpSigningMechanism) SupportsSigning() error {
// Sign creates a (non-detached) signature of input using keyIdentity.
// Fails with a SigningNotSupportedError if the mechanism does not support signing.
-func (m *openpgpSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) {
+func (m *openpgpSigningMechanism) SignWithPassphrase(input []byte, keyIdentity string, passphrase string) ([]byte, error) {
return nil, SigningNotSupportedError("signing is not supported in github.com/containers/image built with the containers_image_openpgp build tag")
}
+// Sign creates a (non-detached) signature of input using keyIdentity.
+// Fails with a SigningNotSupportedError if the mechanism does not support signing.
+func (m *openpgpSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte, error) {
+ return m.SignWithPassphrase(input, keyIdentity, "")
+}
+
// Verify parses unverifiedSignature and returns the content and the signer's identity
func (m *openpgpSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
md, err := openpgp.ReadMessage(bytes.NewReader(unverifiedSignature), m.keyring, nil, nil)
diff --git a/vendor/github.com/containers/image/v5/signature/signature.go b/vendor/github.com/containers/image/v5/signature/signature.go
index 09f4f85e0..05bf8229e 100644
--- a/vendor/github.com/containers/image/v5/signature/signature.go
+++ b/vendor/github.com/containers/image/v5/signature/signature.go
@@ -190,12 +190,20 @@ func (s *untrustedSignature) strictUnmarshalJSON(data []byte) error {
// of the system just because it is a private key — actually the presence of a private key
// on the system increases the likelihood of an a successful attack on that private key
// on that particular system.)
-func (s untrustedSignature) sign(mech SigningMechanism, keyIdentity string) ([]byte, error) {
+func (s untrustedSignature) sign(mech SigningMechanism, keyIdentity string, passphrase string) ([]byte, error) {
json, err := json.Marshal(s)
if err != nil {
return nil, err
}
+ if newMech, ok := mech.(signingMechanismWithPassphrase); ok {
+ return newMech.SignWithPassphrase(json, keyIdentity, passphrase)
+ }
+
+ if passphrase != "" {
+ return nil, errors.New("signing mechanism does not support passphrases")
+ }
+
return mech.Sign(json, keyIdentity)
}
diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go b/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go
index 2110a091d..0bae8b259 100644
--- a/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go
+++ b/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go
@@ -12,7 +12,9 @@ import (
_ "github.com/containers/image/v5/oci/archive"
_ "github.com/containers/image/v5/oci/layout"
_ "github.com/containers/image/v5/openshift"
+ _ "github.com/containers/image/v5/sif"
_ "github.com/containers/image/v5/tarball"
+
// The ostree transport is registered by ostree*.go
// The storage transport is registered by storage*.go
"github.com/containers/image/v5/transports"
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index a743ca7a9..0954850fe 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -6,9 +6,9 @@ const (
// VersionMajor is for an API incompatible changes
VersionMajor = 5
// VersionMinor is for functionality in a backwards-compatible manner
- VersionMinor = 18
+ VersionMinor = 19
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 0
+ VersionPatch = 1
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""
diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod
index fd19d9b48..1489be7c3 100644
--- a/vendor/github.com/containers/psgo/go.mod
+++ b/vendor/github.com/containers/psgo/go.mod
@@ -3,7 +3,8 @@ module github.com/containers/psgo
go 1.14
require (
- github.com/opencontainers/runc v1.0.2
+ github.com/containers/storage v1.38.0
+ github.com/opencontainers/runc v1.1.0
github.com/stretchr/testify v1.7.0
- golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
)
diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum
index 85b0f4ff7..71bfe7abe 100644
--- a/vendor/github.com/containers/psgo/go.sum
+++ b/vendor/github.com/containers/psgo/go.sum
@@ -1,77 +1,1041 @@
+bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+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=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
+github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
+github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
+github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
+github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
+github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
+github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
+github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
+github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
+github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
+github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
+github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
+github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
+github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
+github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
+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/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
+github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
+github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
+github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
+github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
+github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
+github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
+github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
+github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
+github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
+github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
+github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
+github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
+github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E=
+github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
+github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
+github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
+github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
+github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
+github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
+github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
+github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
+github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
+github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
+github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
+github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
+github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
+github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
+github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
+github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
+github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
+github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
+github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
+github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
+github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
+github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
+github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
+github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
+github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
+github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
+github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
+github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU=
+github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
+github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
+github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
+github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
+github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
+github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
+github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
+github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
+github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
+github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
+github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
+github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
+github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
+github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
+github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
+github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
+github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
+github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
+github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
+github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
+github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
+github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw=
+github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y=
+github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
+github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
+github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
+github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
+github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
+github.com/containers/storage v1.38.0 h1:QTgqmtQeb2tk1VucK0nZwCJKmlVLZGybrMMMlixedFY=
+github.com/containers/storage v1.38.0/go.mod h1:lBzt28gAk5ADZuRtwdndRJyqX22vnRaXmlF+7ktfMYc=
+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-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+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/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
+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 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/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
+github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
+github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
+github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
+github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
+github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
+github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
+github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
+github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
+github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
+github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
+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-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
+github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
+github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
+github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
+github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
+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/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+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/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+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/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/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/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
+github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+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/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
+github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/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-middleware v1.0.1-0.20190118093823-f849b5445de4/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/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.0.0/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/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
+github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+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=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
+github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
+github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+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/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
+github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
+github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
+github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
+github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
+github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
-github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/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/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+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 v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
+github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/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.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
+github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
+github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
+github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
+github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
+github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+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/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+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/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+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/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+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.0-20190522114515-bc1a522cf7b1/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/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+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/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+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.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v1.0.0/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-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
+github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
+github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+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/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+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/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
+github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
+github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
+github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
+github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+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/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=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
+github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
+github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
+go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
+go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+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-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+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=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+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-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-20190503192946-f4e77d36d62c/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-20190619014844-b5b0513f8c1b/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/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-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-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo=
-golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+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-20190621195816-6e04913cbbac/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-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+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/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+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-20141024133853-64131543e789/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+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.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
+k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
+k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
+k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
+k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
+k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
+k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
+k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
+k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
+k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
+k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
+k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
+k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
+k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
+k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
+k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
+k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
+k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
+k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
+k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
+k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
+k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
+k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
+k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
+k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
+sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 28ee6a2c9..9e77b865b 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -19,13 +19,9 @@ import (
"fmt"
"io"
"os"
-)
-type IDMap struct {
- ContainerID int
- HostID int
- Size int
-}
+ "github.com/containers/storage/pkg/idtools"
+)
// ParsePIDNamespace returns the content of /proc/$pid/ns/pid.
func ParsePIDNamespace(pid string) (string, error) {
@@ -46,14 +42,14 @@ func ParseUserNamespace(pid string) (string, error) {
}
// ReadMappings reads the user namespace mappings at the specified path
-func ReadMappings(path string) ([]IDMap, error) {
+func ReadMappings(path string) ([]idtools.IDMap, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
- mappings := []IDMap{}
+ var mappings []idtools.IDMap
buf := bufio.NewReader(file)
for {
@@ -68,10 +64,10 @@ func ReadMappings(path string) ([]IDMap, error) {
return mappings, nil
}
- containerID, hostID, size := 0, 0, 0
+ var containerID, hostID, size int
if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil {
return nil, fmt.Errorf("cannot parse %s: %w", string(line), err)
}
- mappings = append(mappings, IDMap{ContainerID: containerID, HostID: hostID, Size: size})
+ mappings = append(mappings, idtools.IDMap{ContainerID: containerID, HostID: hostID, Size: size})
}
}
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 1896b5c07..1d2247cbd 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -18,8 +18,11 @@ import (
"bufio"
"fmt"
"os"
- "os/exec"
+ "strconv"
"strings"
+ "sync"
+
+ "github.com/containers/storage/pkg/idtools"
)
// Status is a direct translation of a `/proc/[pid]/status`, which provides much
@@ -173,23 +176,8 @@ type Status struct {
NonvoluntaryCtxtSwitches string
}
-// readStatusUserNS joins the user namespace of pid and returns the content of
-// /proc/pid/status as a string slice.
-func readStatusUserNS(pid string) ([]string, error) {
- path := fmt.Sprintf("/proc/%s/status", pid)
- args := []string{"nsenter", "-U", "-t", pid, "cat", path}
-
- c := exec.Command(args[0], args[1:]...)
- output, err := c.CombinedOutput()
- if err != nil {
- return nil, fmt.Errorf("error executing %q: %w", strings.Join(args, " "), err)
- }
-
- return strings.Split(string(output), "\n"), nil
-}
-
-// readStatusDefault returns the content of /proc/pid/status as a string slice.
-func readStatusDefault(pid string) ([]string, error) {
+// readStatus returns the content of /proc/pid/status as a string slice.
+func readStatus(pid string) ([]string, error) {
path := fmt.Sprintf("/proc/%s/status", pid)
f, err := os.Open(path)
if err != nil {
@@ -203,21 +191,81 @@ func readStatusDefault(pid string) ([]string, error) {
return lines, nil
}
-// ParseStatus parses the /proc/$pid/status file and returns a *Status.
-func ParseStatus(pid string, joinUserNS bool) (*Status, error) {
- var lines []string
- var err error
+// mapField maps a single string-typed ID field given the set of mappings. If
+// no mapping exists, the overflow uid/gid is used.
+func mapStatusField(field *string, mapping []idtools.IDMap, overflow string) {
+ hostId, err := strconv.Atoi(*field)
+ if err != nil {
+ *field = overflow
+ return
+ }
+ contId, err := idtools.RawToContainer(hostId, mapping)
+ if err != nil {
+ *field = overflow
+ return
+ }
+ *field = strconv.Itoa(contId)
+}
- if joinUserNS {
- lines, err = readStatusUserNS(pid)
- } else {
- lines, err = readStatusDefault(pid)
+var (
+ overflowOnce sync.Once
+ overflowUid = "65534"
+ overflowGid = "65534"
+)
+
+func overflowIds() (string, string) {
+ overflowOnce.Do(func() {
+ if uid, err := os.ReadFile("/proc/sys/kernel/overflowuid"); err == nil {
+ overflowUid = strings.TrimSpace(string(uid))
+ }
+ if gid, err := os.ReadFile("/proc/sys/kernel/overflowgid"); err == nil {
+ overflowGid = strings.TrimSpace(string(gid))
+ }
+ })
+ return overflowUid, overflowGid
+}
+
+// mapStatus takes a Status struct and remaps all of the relevant fields to
+// match the user namespace of the target process.
+func mapStatus(pid string, status *Status) (*Status, error) {
+ uidMap, err := ReadMappings(fmt.Sprintf("/proc/%s/uid_map", pid))
+ if err != nil {
+ return nil, err
+ }
+ gidMap, err := ReadMappings(fmt.Sprintf("/proc/%s/gid_map", pid))
+ if err != nil {
+ return nil, err
+ }
+ overflowUid, overflowGid := overflowIds()
+ for i := range status.Uids {
+ mapStatusField(&status.Uids[i], uidMap, overflowUid)
+ }
+ for i := range status.Gids {
+ mapStatusField(&status.Gids[i], gidMap, overflowGid)
}
+ for i := range status.Groups {
+ mapStatusField(&status.Groups[i], gidMap, overflowGid)
+ }
+ return status, nil
+}
+// ParseStatus parses the /proc/$pid/status file and returns a *Status.
+func ParseStatus(pid string, mapUserNS bool) (*Status, error) {
+ lines, err := readStatus(pid)
+ if err != nil {
+ return nil, err
+ }
+ status, err := parseStatus(pid, lines)
if err != nil {
return nil, err
}
- return parseStatus(pid, lines)
+ if mapUserNS {
+ status, err = mapStatus(pid, status)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return status, nil
}
// parseStatus extracts data from lines and returns a *Status.
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index ea893e7ca..d6cfcef4d 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -41,28 +41,18 @@ import (
"github.com/containers/psgo/internal/dev"
"github.com/containers/psgo/internal/proc"
"github.com/containers/psgo/internal/process"
+ "github.com/containers/storage/pkg/idtools"
"golang.org/x/sys/unix"
)
-// IDMap specifies a mapping range from the host to the container IDs.
-type IDMap struct {
- // ContainerID is the first ID in the container.
- ContainerID int
- // HostID is the first ID in the host.
- HostID int
- // Size specifies how long is the range. e.g. 1 means a single user
- // is mapped.
- Size int
-}
-
// JoinNamespaceOpts specifies different options for joining the specified namespaces.
type JoinNamespaceOpts struct {
// UIDMap specifies a mapping for UIDs in the container. If specified
// huser will perform the reverse mapping.
- UIDMap []IDMap
+ UIDMap []idtools.IDMap
// GIDMap specifies a mapping for GIDs in the container. If specified
// hgroup will perform the reverse mapping.
- GIDMap []IDMap
+ GIDMap []idtools.IDMap
// FillMappings specified whether UIDMap and GIDMap must be initialized
// with the current user namespace.
@@ -102,7 +92,7 @@ type aixFormatDescriptor struct {
}
// findID converts the specified id to the host mapping
-func findID(idStr string, mapping []IDMap, lookupFunc func(uid string) (string, error), overflowFile string) (string, error) {
+func findID(idStr string, mapping []idtools.IDMap, lookupFunc func(uid string) (string, error), overflowFile string) (string, error) {
if len(mapping) == 0 {
return idStr, nil
}
@@ -350,29 +340,16 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
return JoinNamespaceAndProcessInfoWithOptions(pid, descriptors, &JoinNamespaceOpts{})
}
-func readMappings(path string) ([]IDMap, error) {
- mappings, err := proc.ReadMappings(path)
- if err != nil {
- return nil, err
- }
- var res []IDMap
- for _, i := range mappings {
- m := IDMap{ContainerID: i.ContainerID, HostID: i.HostID, Size: i.Size}
- res = append(res, m)
- }
- return res, nil
-}
-
func contextFromOptions(options *JoinNamespaceOpts) (*psContext, error) {
ctx := new(psContext)
ctx.opts = options
if ctx.opts != nil && ctx.opts.FillMappings {
- uidMappings, err := readMappings("/proc/self/uid_map")
+ uidMappings, err := proc.ReadMappings("/proc/self/uid_map")
if err != nil {
return nil, err
}
- gidMappings, err := readMappings("/proc/self/gid_map")
+ gidMappings, err := proc.ReadMappings("/proc/self/gid_map")
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/storage/Makefile b/vendor/github.com/containers/storage/Makefile
index dbc1f7c99..d7ca0c1c4 100644
--- a/vendor/github.com/containers/storage/Makefile
+++ b/vendor/github.com/containers/storage/Makefile
@@ -51,6 +51,9 @@ sources := $(wildcard *.go cmd/containers-storage/*.go drivers/*.go drivers/*/*.
containers-storage: $(sources) ## build using gc on the host
$(GO) build $(MOD_VENDOR) -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
+codespell:
+ codespell -S Makefile,build,buildah,buildah.spec,imgtype,copy,AUTHORS,bin,vendor,.git,go.sum,CHANGELOG.md,changelog.txt,seccomp.json,.cirrus.yml,"*.xz,*.gz,*.tar,*.tgz,*ico,*.png,*.1,*.5,*.orig,*.rej" -L flate,uint,iff,od,ERRO -w
+
binary local-binary: containers-storage
local-gccgo: ## build using gccgo on the host
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 97dd8ea50..c85090d66 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.37.0+dev
+1.38.2
diff --git a/vendor/github.com/containers/storage/drivers/fsdiff.go b/vendor/github.com/containers/storage/drivers/fsdiff.go
index a534630df..b7e681ace 100644
--- a/vendor/github.com/containers/storage/drivers/fsdiff.go
+++ b/vendor/github.com/containers/storage/drivers/fsdiff.go
@@ -138,6 +138,7 @@ func (gdw *NaiveDiffDriver) Changes(id string, idMappings *idtools.IDMappings, p
if parent != "" {
options := MountOpts{
MountLabel: mountLabel,
+ Options: []string{"ro"},
}
parentFs, err = driver.Get(parent, options)
if err != nil {
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index 15ba57467..b22f9dfb2 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -1055,17 +1055,22 @@ func (d *Driver) getLower(parent string) (string, error) {
}
func (d *Driver) dir(id string) string {
+ p, _ := d.dir2(id)
+ return p
+}
+
+func (d *Driver) dir2(id string) (string, bool) {
newpath := path.Join(d.home, id)
if _, err := os.Stat(newpath); err != nil {
for _, p := range d.AdditionalImageStores() {
l := path.Join(p, d.name, id)
_, err = os.Stat(l)
if err == nil {
- return l
+ return l, true
}
}
}
- return newpath
+ return newpath, false
}
func (d *Driver) getLowerDirs(id string) ([]string, error) {
@@ -1260,11 +1265,11 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr
func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountOpts) (_ string, retErr error) {
d.locker.Lock(id)
defer d.locker.Unlock(id)
- dir := d.dir(id)
+ dir, inAdditionalStore := d.dir2(id)
if _, err := os.Stat(dir); err != nil {
return "", err
}
- readWrite := true
+ readWrite := !inAdditionalStore
if !d.SupportsShifting() || options.DisableShifting {
disableShifting = true
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 96ca1f0b2..a2aff4902 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -3,22 +3,22 @@ go 1.14
module github.com/containers/storage
require (
- github.com/BurntSushi/toml v0.4.1
+ github.com/BurntSushi/toml v1.0.0
github.com/Microsoft/go-winio v0.5.1
- github.com/Microsoft/hcsshim v0.9.1
- github.com/containerd/stargz-snapshotter/estargz v0.10.1
+ github.com/Microsoft/hcsshim v0.9.2
+ github.com/containerd/stargz-snapshotter/estargz v0.11.0
github.com/cyphar/filepath-securejoin v0.2.3
github.com/docker/go-units v0.4.0
github.com/google/go-intervals v0.0.2
github.com/hashicorp/go-multierror v1.1.1
github.com/json-iterator/go v1.1.12
- github.com/klauspost/compress v1.13.6
+ github.com/klauspost/compress v1.14.2
github.com/klauspost/pgzip v1.2.5
github.com/mattn/go-shellwords v1.0.12
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/moby/sys/mountinfo v0.5.0
github.com/opencontainers/go-digest v1.0.0
- github.com/opencontainers/runc v1.0.3
+ github.com/opencontainers/runc v1.1.0
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/selinux v1.10.0
github.com/pkg/errors v0.9.1
@@ -29,6 +29,6 @@ require (
github.com/ulikunitz/xz v0.5.10
github.com/vbatts/tar-split v0.11.2
golang.org/x/net v0.0.0-20210825183410-e898025ed96a
- golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
+ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
gotest.tools v2.2.0+incompatible
)
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index c7262fe7a..b211efd37 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -36,8 +36,8 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
-github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
+github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
@@ -57,8 +57,8 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
-github.com/Microsoft/hcsshim v0.9.1 h1:VfDCj+QnY19ktX5TsH22JHcjaZ05RWQiwDbOyEg5ziM=
-github.com/Microsoft/hcsshim v0.9.1/go.mod h1:Y/0uV2jUab5kBI7SQgl62at0AVX7uaruzADAVmxm3eM=
+github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY=
+github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -98,6 +98,7 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -106,6 +107,7 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -131,6 +133,7 @@ github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@@ -173,8 +176,8 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
-github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng=
-github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0 h1:t0IW5kOmY7AXDAWRUs2uVzDhijAUOAYVr/dyRhOQvBg=
+github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -296,6 +299,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -420,8 +424,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
-github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
+github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -515,8 +519,8 @@ github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
-github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
+github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -578,6 +582,7 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
+github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
@@ -839,8 +844,11 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go
index e7c4cfcf1..677a15edd 100644
--- a/vendor/github.com/containers/storage/pkg/archive/archive.go
+++ b/vendor/github.com/containers/storage/pkg/archive/archive.go
@@ -511,6 +511,10 @@ func (ta *tarAppender) addTarFile(path, name string) error {
return err
}
}
+ if fi.Mode()&os.ModeSocket != 0 {
+ logrus.Warnf("archive: skipping %q since it is a socket", path)
+ return nil
+ }
hdr, err := FileInfoHeader(name, fi, link)
if err != nil {
@@ -969,7 +973,10 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
whiteoutConverter := GetWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData)
buffer := make([]byte, 1<<20)
+ doChown := !options.NoLchown
if options.ForceMask != nil {
+ // if ForceMask is in place, make sure lchown is disabled.
+ doChown = false
uid, gid, mode, err := GetFileOwner(dest)
if err == nil {
value := fmt.Sprintf("%d:%d:0%o", uid, gid, mode)
@@ -1074,7 +1081,7 @@ loop:
chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid}
}
- if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, chownOpts, options.InUserNS, options.IgnoreChownErrors, options.ForceMask, buffer); err != nil {
+ if err = createTarFile(path, dest, hdr, trBuf, doChown, chownOpts, options.InUserNS, options.IgnoreChownErrors, options.ForceMask, buffer); err != nil {
return err
}
diff --git a/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go
new file mode 100644
index 000000000..a931fb5d1
--- /dev/null
+++ b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go
@@ -0,0 +1,630 @@
+package chunked
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+ "unsafe"
+
+ storage "github.com/containers/storage"
+ "github.com/containers/storage/pkg/chunked/internal"
+ "github.com/containers/storage/pkg/ioutils"
+ jsoniter "github.com/json-iterator/go"
+ digest "github.com/opencontainers/go-digest"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ cacheKey = "chunked-manifest-cache"
+ cacheVersion = 1
+)
+
+type metadata struct {
+ tagLen int
+ digestLen int
+ tags []byte
+ vdata []byte
+}
+
+type layer struct {
+ id string
+ metadata *metadata
+ target string
+}
+
+type layersCache struct {
+ layers []layer
+ refs int
+ store storage.Store
+ mutex sync.RWMutex
+ created time.Time
+}
+
+var cacheMutex sync.Mutex
+var cache *layersCache
+
+func (c *layersCache) release() {
+ cacheMutex.Lock()
+ defer cacheMutex.Unlock()
+
+ c.refs--
+ if c.refs == 0 {
+ cache = nil
+ }
+}
+
+func getLayersCacheRef(store storage.Store) *layersCache {
+ cacheMutex.Lock()
+ defer cacheMutex.Unlock()
+ if cache != nil && cache.store == store && time.Since(cache.created).Minutes() < 10 {
+ cache.refs++
+ return cache
+ }
+ cache := &layersCache{
+ store: store,
+ refs: 1,
+ created: time.Now(),
+ }
+ return cache
+}
+
+func getLayersCache(store storage.Store) (*layersCache, error) {
+ c := getLayersCacheRef(store)
+
+ if err := c.load(); err != nil {
+ c.release()
+ return nil, err
+ }
+ return c, nil
+}
+
+func (c *layersCache) load() error {
+ c.mutex.Lock()
+ defer c.mutex.Unlock()
+
+ allLayers, err := c.store.Layers()
+ if err != nil {
+ return err
+ }
+ existingLayers := make(map[string]string)
+ for _, r := range c.layers {
+ existingLayers[r.id] = r.target
+ }
+
+ currentLayers := make(map[string]string)
+ for _, r := range allLayers {
+ currentLayers[r.ID] = r.ID
+ if _, found := existingLayers[r.ID]; found {
+ continue
+ }
+
+ bigData, err := c.store.LayerBigData(r.ID, cacheKey)
+ if err != nil {
+ if errors.Cause(err) == os.ErrNotExist {
+ continue
+ }
+ return err
+ }
+ defer bigData.Close()
+
+ metadata, err := readMetadataFromCache(bigData)
+ if err != nil {
+ logrus.Warningf("Error reading cache file for layer %q: %v", r.ID, err)
+ }
+
+ if metadata != nil {
+ c.addLayer(r.ID, metadata)
+ continue
+ }
+
+ manifestReader, err := c.store.LayerBigData(r.ID, bigDataKey)
+ if err != nil {
+ continue
+ }
+ defer manifestReader.Close()
+ manifest, err := ioutil.ReadAll(manifestReader)
+ if err != nil {
+ return fmt.Errorf("open manifest file for layer %q: %w", r.ID, err)
+ }
+
+ metadata, err = writeCache(manifest, r.ID, c.store)
+ if err == nil {
+ c.addLayer(r.ID, metadata)
+ }
+ }
+
+ var newLayers []layer
+ for _, l := range c.layers {
+ if _, found := currentLayers[l.id]; found {
+ newLayers = append(newLayers, l)
+ }
+ }
+ c.layers = newLayers
+
+ return nil
+}
+
+// calculateHardLinkFingerprint calculates a hash that can be used to verify if a file
+// is usable for deduplication with hardlinks.
+// To calculate the digest, it uses the file payload digest, UID, GID, mode and xattrs.
+func calculateHardLinkFingerprint(f *internal.FileMetadata) (string, error) {
+ digester := digest.Canonical.Digester()
+
+ modeString := fmt.Sprintf("%d:%d:%o", f.UID, f.GID, f.Mode)
+ hash := digester.Hash()
+
+ if _, err := hash.Write([]byte(f.Digest)); err != nil {
+ return "", err
+ }
+
+ if _, err := hash.Write([]byte(modeString)); err != nil {
+ return "", err
+ }
+
+ if len(f.Xattrs) > 0 {
+ keys := make([]string, 0, len(f.Xattrs))
+ for k := range f.Xattrs {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ if _, err := hash.Write([]byte(k)); err != nil {
+ return "", err
+ }
+ if _, err := hash.Write([]byte(f.Xattrs[k])); err != nil {
+ return "", err
+ }
+ }
+ }
+ return string(digester.Digest()), nil
+}
+
+// generateFileLocation generates a file location in the form $OFFSET@$PATH
+func generateFileLocation(path string, offset uint64) []byte {
+ return []byte(fmt.Sprintf("%d@%s", offset, path))
+}
+
+// generateTag generates a tag in the form $DIGEST$OFFSET@LEN.
+// the [OFFSET; LEN] points to the variable length data where the file locations
+// are stored. $DIGEST has length digestLen stored in the metadata file header.
+func generateTag(digest string, offset, len uint64) string {
+ return fmt.Sprintf("%s%.20d@%.20d", digest, offset, len)
+}
+
+type setBigData interface {
+ // SetLayerBigData stores a (possibly large) chunk of named data
+ SetLayerBigData(id, key string, data io.Reader) error
+}
+
+// writeCache write a cache for the layer ID.
+// It generates a sorted list of digests with their offset to the path location and offset.
+// The same cache is used to lookup files, chunks and candidates for deduplication with hard links.
+// There are 3 kind of digests stored:
+// - digest(file.payload))
+// - digest(digest(file.payload) + file.UID + file.GID + file.mode + file.xattrs)
+// - digest(i) for each i in chunks(file payload)
+func writeCache(manifest []byte, id string, dest setBigData) (*metadata, error) {
+ var vdata bytes.Buffer
+ tagLen := 0
+ digestLen := 0
+ var tagsBuffer bytes.Buffer
+
+ toc, err := prepareMetadata(manifest)
+ if err != nil {
+ return nil, err
+ }
+
+ var tags []string
+ for _, k := range toc {
+ if k.Digest != "" {
+ location := generateFileLocation(k.Name, 0)
+
+ off := uint64(vdata.Len())
+ l := uint64(len(location))
+
+ d := generateTag(k.Digest, off, l)
+ if tagLen == 0 {
+ tagLen = len(d)
+ }
+ if tagLen != len(d) {
+ return nil, errors.New("digest with different length found")
+ }
+ tags = append(tags, d)
+
+ fp, err := calculateHardLinkFingerprint(k)
+ if err != nil {
+ return nil, err
+ }
+ d = generateTag(fp, off, l)
+ if tagLen != len(d) {
+ return nil, errors.New("digest with different length found")
+ }
+ tags = append(tags, d)
+
+ if _, err := vdata.Write(location); err != nil {
+ return nil, err
+ }
+
+ digestLen = len(k.Digest)
+ }
+ if k.ChunkDigest != "" {
+ location := generateFileLocation(k.Name, uint64(k.ChunkOffset))
+ off := uint64(vdata.Len())
+ l := uint64(len(location))
+ d := generateTag(k.ChunkDigest, off, l)
+ if tagLen == 0 {
+ tagLen = len(d)
+ }
+ if tagLen != len(d) {
+ return nil, errors.New("digest with different length found")
+ }
+ tags = append(tags, d)
+
+ if _, err := vdata.Write(location); err != nil {
+ return nil, err
+ }
+ digestLen = len(k.ChunkDigest)
+ }
+ }
+
+ sort.Strings(tags)
+
+ for _, t := range tags {
+ if _, err := tagsBuffer.Write([]byte(t)); err != nil {
+ return nil, err
+ }
+ }
+
+ pipeReader, pipeWriter := io.Pipe()
+ errChan := make(chan error, 1)
+ go func() {
+ defer pipeWriter.Close()
+ defer close(errChan)
+
+ // version
+ if err := binary.Write(pipeWriter, binary.LittleEndian, uint64(cacheVersion)); err != nil {
+ errChan <- err
+ return
+ }
+
+ // len of a tag
+ if err := binary.Write(pipeWriter, binary.LittleEndian, uint64(tagLen)); err != nil {
+ errChan <- err
+ return
+ }
+
+ // len of a digest
+ if err := binary.Write(pipeWriter, binary.LittleEndian, uint64(digestLen)); err != nil {
+ errChan <- err
+ return
+ }
+
+ // tags length
+ if err := binary.Write(pipeWriter, binary.LittleEndian, uint64(tagsBuffer.Len())); err != nil {
+ errChan <- err
+ return
+ }
+
+ // vdata length
+ if err := binary.Write(pipeWriter, binary.LittleEndian, uint64(vdata.Len())); err != nil {
+ errChan <- err
+ return
+ }
+
+ // tags
+ if _, err := pipeWriter.Write(tagsBuffer.Bytes()); err != nil {
+ errChan <- err
+ return
+ }
+
+ // variable length data
+ if _, err := pipeWriter.Write(vdata.Bytes()); err != nil {
+ errChan <- err
+ return
+ }
+
+ errChan <- nil
+ }()
+ defer pipeReader.Close()
+
+ counter := ioutils.NewWriteCounter(ioutil.Discard)
+
+ r := io.TeeReader(pipeReader, counter)
+
+ if err := dest.SetLayerBigData(id, cacheKey, r); err != nil {
+ return nil, err
+ }
+
+ if err := <-errChan; err != nil {
+ return nil, err
+ }
+
+ logrus.Debugf("Written lookaside cache for layer %q with length %v", id, counter.Count)
+
+ return &metadata{
+ digestLen: digestLen,
+ tagLen: tagLen,
+ tags: tagsBuffer.Bytes(),
+ vdata: vdata.Bytes(),
+ }, nil
+}
+
+func readMetadataFromCache(bigData io.Reader) (*metadata, error) {
+ var version, tagLen, digestLen, tagsLen, vdataLen uint64
+ if err := binary.Read(bigData, binary.LittleEndian, &version); err != nil {
+ return nil, err
+ }
+ if version != cacheVersion {
+ return nil, nil
+ }
+ if err := binary.Read(bigData, binary.LittleEndian, &tagLen); err != nil {
+ return nil, err
+ }
+ if err := binary.Read(bigData, binary.LittleEndian, &digestLen); err != nil {
+ return nil, err
+ }
+ if err := binary.Read(bigData, binary.LittleEndian, &tagsLen); err != nil {
+ return nil, err
+ }
+ if err := binary.Read(bigData, binary.LittleEndian, &vdataLen); err != nil {
+ return nil, err
+ }
+
+ tags := make([]byte, tagsLen)
+ if _, err := bigData.Read(tags); err != nil {
+ return nil, err
+ }
+
+ vdata := make([]byte, vdataLen)
+ if _, err := bigData.Read(vdata); err != nil {
+ return nil, err
+ }
+
+ return &metadata{
+ tagLen: int(tagLen),
+ digestLen: int(digestLen),
+ tags: tags,
+ vdata: vdata,
+ }, nil
+}
+
+func prepareMetadata(manifest []byte) ([]*internal.FileMetadata, error) {
+ toc, err := unmarshalToc(manifest)
+ if err != nil {
+ // ignore errors here. They might be caused by a different manifest format.
+ return nil, nil
+ }
+
+ var r []*internal.FileMetadata
+ chunkSeen := make(map[string]bool)
+ for i := range toc.Entries {
+ d := toc.Entries[i].Digest
+ if d != "" {
+ r = append(r, &toc.Entries[i])
+ continue
+ }
+
+ // chunks do not use hard link dedup so keeping just one candidate is enough
+ cd := toc.Entries[i].ChunkDigest
+ if cd != "" && !chunkSeen[cd] {
+ r = append(r, &toc.Entries[i])
+ chunkSeen[cd] = true
+ }
+ }
+ return r, nil
+}
+
+func (c *layersCache) addLayer(id string, metadata *metadata) error {
+ target, err := c.store.DifferTarget(id)
+ if err != nil {
+ return fmt.Errorf("get checkout directory layer %q: %w", id, err)
+ }
+
+ l := layer{
+ id: id,
+ metadata: metadata,
+ target: target,
+ }
+ c.layers = append(c.layers, l)
+ return nil
+}
+
+func byteSliceAsString(b []byte) string {
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+func findTag(digest string, metadata *metadata) (string, uint64, uint64) {
+ if len(digest) != metadata.digestLen {
+ return "", 0, 0
+ }
+
+ nElements := len(metadata.tags) / metadata.tagLen
+
+ i := sort.Search(nElements, func(i int) bool {
+ d := byteSliceAsString(metadata.tags[i*metadata.tagLen : i*metadata.tagLen+metadata.digestLen])
+ return strings.Compare(d, digest) >= 0
+ })
+ if i < nElements {
+ d := string(metadata.tags[i*metadata.tagLen : i*metadata.tagLen+len(digest)])
+ if digest == d {
+ startOff := i*metadata.tagLen + metadata.digestLen
+ parts := strings.Split(string(metadata.tags[startOff:(i+1)*metadata.tagLen]), "@")
+ off, _ := strconv.ParseInt(parts[0], 10, 64)
+ len, _ := strconv.ParseInt(parts[1], 10, 64)
+ return digest, uint64(off), uint64(len)
+ }
+ }
+ return "", 0, 0
+}
+
+func (c *layersCache) findDigestInternal(digest string) (string, string, int64, error) {
+ if digest == "" {
+ return "", "", -1, nil
+ }
+
+ c.mutex.RLock()
+ defer c.mutex.RUnlock()
+
+ for _, layer := range c.layers {
+ digest, off, len := findTag(digest, layer.metadata)
+ if digest != "" {
+ position := string(layer.metadata.vdata[off : off+len])
+ parts := strings.SplitN(position, "@", 2)
+ offFile, _ := strconv.ParseInt(parts[0], 10, 64)
+ return layer.target, parts[1], offFile, nil
+ }
+ }
+
+ return "", "", -1, nil
+}
+
+// findFileInOtherLayers finds the specified file in other layers.
+// file is the file to look for.
+func (c *layersCache) findFileInOtherLayers(file *internal.FileMetadata, useHardLinks bool) (string, string, error) {
+ digest := file.Digest
+ if useHardLinks {
+ var err error
+ digest, err = calculateHardLinkFingerprint(file)
+ if err != nil {
+ return "", "", err
+ }
+ }
+ target, name, off, err := c.findDigestInternal(digest)
+ if off == 0 {
+ return target, name, err
+ }
+ return "", "", nil
+}
+
+func (c *layersCache) findChunkInOtherLayers(chunk *internal.FileMetadata) (string, string, int64, error) {
+ return c.findDigestInternal(chunk.ChunkDigest)
+}
+
+func unmarshalToc(manifest []byte) (*internal.TOC, error) {
+ var buf bytes.Buffer
+ count := 0
+ var toc internal.TOC
+
+ iter := jsoniter.ParseBytes(jsoniter.ConfigFastest, manifest)
+ for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
+ if field != "entries" {
+ iter.Skip()
+ continue
+ }
+ for iter.ReadArray() {
+ for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
+ switch field {
+ case "type", "name", "linkName", "digest", "chunkDigest", "chunkType":
+ count += len(iter.ReadStringAsSlice())
+ case "xattrs":
+ for key := iter.ReadObject(); key != ""; key = iter.ReadObject() {
+ count += len(iter.ReadStringAsSlice())
+ }
+ default:
+ iter.Skip()
+ }
+ }
+ }
+ break
+ }
+
+ buf.Grow(count)
+
+ getString := func(b []byte) string {
+ from := buf.Len()
+ buf.Write(b)
+ to := buf.Len()
+ return byteSliceAsString(buf.Bytes()[from:to])
+ }
+
+ iter = jsoniter.ParseBytes(jsoniter.ConfigFastest, manifest)
+ for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
+ if field == "version" {
+ toc.Version = iter.ReadInt()
+ continue
+ }
+ if field != "entries" {
+ iter.Skip()
+ continue
+ }
+ for iter.ReadArray() {
+ var m internal.FileMetadata
+ for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
+ switch field {
+ case "type":
+ m.Type = getString(iter.ReadStringAsSlice())
+ case "name":
+ m.Name = getString(iter.ReadStringAsSlice())
+ case "linkName":
+ m.Linkname = getString(iter.ReadStringAsSlice())
+ case "mode":
+ m.Mode = iter.ReadInt64()
+ case "size":
+ m.Size = iter.ReadInt64()
+ case "UID":
+ m.UID = iter.ReadInt()
+ case "GID":
+ m.GID = iter.ReadInt()
+ case "ModTime":
+ time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
+ if err != nil {
+ return nil, err
+ }
+ m.ModTime = &time
+ case "accesstime":
+ time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
+ if err != nil {
+ return nil, err
+ }
+ m.AccessTime = &time
+ case "changetime":
+ time, err := time.Parse(time.RFC3339, byteSliceAsString(iter.ReadStringAsSlice()))
+ if err != nil {
+ return nil, err
+ }
+ m.ChangeTime = &time
+ case "devMajor":
+ m.Devmajor = iter.ReadInt64()
+ case "devMinor":
+ m.Devminor = iter.ReadInt64()
+ case "digest":
+ m.Digest = getString(iter.ReadStringAsSlice())
+ case "offset":
+ m.Offset = iter.ReadInt64()
+ case "endOffset":
+ m.EndOffset = iter.ReadInt64()
+ case "chunkSize":
+ m.ChunkSize = iter.ReadInt64()
+ case "chunkOffset":
+ m.ChunkOffset = iter.ReadInt64()
+ case "chunkDigest":
+ m.ChunkDigest = getString(iter.ReadStringAsSlice())
+ case "chunkType":
+ m.ChunkType = getString(iter.ReadStringAsSlice())
+ case "xattrs":
+ m.Xattrs = make(map[string]string)
+ for key := iter.ReadObject(); key != ""; key = iter.ReadObject() {
+ value := iter.ReadStringAsSlice()
+ m.Xattrs[key] = getString(value)
+ }
+ default:
+ iter.Skip()
+ }
+ }
+ toc.Entries = append(toc.Entries, m)
+ }
+ break
+ }
+ toc.StringsBuf = buf
+ return &toc, nil
+}
diff --git a/vendor/github.com/containers/storage/pkg/chunked/compressor/compressor.go b/vendor/github.com/containers/storage/pkg/chunked/compressor/compressor.go
index 092cf584a..aeb7cfd4f 100644
--- a/vendor/github.com/containers/storage/pkg/chunked/compressor/compressor.go
+++ b/vendor/github.com/containers/storage/pkg/chunked/compressor/compressor.go
@@ -5,6 +5,7 @@ package compressor
// larger software like the graph drivers.
import (
+ "bufio"
"encoding/base64"
"io"
"io/ioutil"
@@ -15,6 +16,189 @@ import (
"github.com/vbatts/tar-split/archive/tar"
)
+const RollsumBits = 16
+const holesThreshold = int64(1 << 10)
+
+type holesFinder struct {
+ reader *bufio.Reader
+ fileOff int64
+ zeros int64
+ from int64
+ threshold int64
+
+ state int
+}
+
+const (
+ holesFinderStateRead = iota
+ holesFinderStateAccumulate
+ holesFinderStateFound
+ holesFinderStateEOF
+)
+
+// ReadByte reads a single byte from the underlying reader.
+// If a single byte is read, the return value is (0, RAW-BYTE-VALUE, nil).
+// If there are at least f.THRESHOLD consecutive zeros, then the
+// return value is (N_CONSECUTIVE_ZEROS, '\x00').
+func (f *holesFinder) ReadByte() (int64, byte, error) {
+ for {
+ switch f.state {
+ // reading the file stream
+ case holesFinderStateRead:
+ if f.zeros > 0 {
+ f.zeros--
+ return 0, 0, nil
+ }
+ b, err := f.reader.ReadByte()
+ if err != nil {
+ return 0, b, err
+ }
+
+ if b != 0 {
+ return 0, b, err
+ }
+
+ f.zeros = 1
+ if f.zeros == f.threshold {
+ f.state = holesFinderStateFound
+ } else {
+ f.state = holesFinderStateAccumulate
+ }
+ // accumulating zeros, but still didn't reach the threshold
+ case holesFinderStateAccumulate:
+ b, err := f.reader.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ f.state = holesFinderStateEOF
+ continue
+ }
+ return 0, b, err
+ }
+
+ if b == 0 {
+ f.zeros++
+ if f.zeros == f.threshold {
+ f.state = holesFinderStateFound
+ }
+ } else {
+ if f.reader.UnreadByte(); err != nil {
+ return 0, 0, err
+ }
+ f.state = holesFinderStateRead
+ }
+ // found a hole. Number of zeros >= threshold
+ case holesFinderStateFound:
+ b, err := f.reader.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ f.state = holesFinderStateEOF
+ }
+ holeLen := f.zeros
+ f.zeros = 0
+ return holeLen, 0, nil
+ }
+ if b != 0 {
+ if f.reader.UnreadByte(); err != nil {
+ return 0, 0, err
+ }
+ f.state = holesFinderStateRead
+
+ holeLen := f.zeros
+ f.zeros = 0
+ return holeLen, 0, nil
+ }
+ f.zeros++
+ // reached EOF. Flush pending zeros if any.
+ case holesFinderStateEOF:
+ if f.zeros > 0 {
+ f.zeros--
+ return 0, 0, nil
+ }
+ return 0, 0, io.EOF
+ }
+ }
+}
+
+type rollingChecksumReader struct {
+ reader *holesFinder
+ closed bool
+ rollsum *RollSum
+ pendingHole int64
+
+ // WrittenOut is the total number of bytes read from
+ // the stream.
+ WrittenOut int64
+
+ // IsLastChunkZeros tells whether the last generated
+ // chunk is a hole (made of consecutive zeros). If it
+ // is false, then the last chunk is a data chunk
+ // generated by the rolling checksum.
+ IsLastChunkZeros bool
+}
+
+func (rc *rollingChecksumReader) Read(b []byte) (bool, int, error) {
+ rc.IsLastChunkZeros = false
+
+ if rc.pendingHole > 0 {
+ toCopy := int64(len(b))
+ if rc.pendingHole < toCopy {
+ toCopy = rc.pendingHole
+ }
+ rc.pendingHole -= toCopy
+ for i := int64(0); i < toCopy; i++ {
+ b[i] = 0
+ }
+
+ rc.WrittenOut += toCopy
+
+ rc.IsLastChunkZeros = true
+
+ // if there are no other zeros left, terminate the chunk
+ return rc.pendingHole == 0, int(toCopy), nil
+ }
+
+ if rc.closed {
+ return false, 0, io.EOF
+ }
+
+ for i := 0; i < len(b); i++ {
+ holeLen, n, err := rc.reader.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ rc.closed = true
+ if i == 0 {
+ return false, 0, err
+ }
+ return false, i, nil
+ }
+ // Report any other error type
+ return false, -1, err
+ }
+ if holeLen > 0 {
+ for j := int64(0); j < holeLen; j++ {
+ rc.rollsum.Roll(0)
+ }
+ rc.pendingHole = holeLen
+ return true, i, nil
+ }
+ b[i] = n
+ rc.WrittenOut++
+ rc.rollsum.Roll(n)
+ if rc.rollsum.OnSplitWithBits(RollsumBits) {
+ return true, i + 1, nil
+ }
+ }
+ return false, len(b), nil
+}
+
+type chunk struct {
+ ChunkOffset int64
+ Offset int64
+ Checksum string
+ ChunkSize int64
+ ChunkType string
+}
+
func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, reader io.Reader, level int) error {
// total written so far. Used to retrieve partial offsets in the file
dest := ioutils.NewWriteCounter(destFile)
@@ -64,40 +248,78 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
if _, err := zstdWriter.Write(rawBytes); err != nil {
return err
}
- payloadDigester := digest.Canonical.Digester()
- payloadChecksum := payloadDigester.Hash()
- payloadDest := io.MultiWriter(payloadChecksum, zstdWriter)
+ payloadDigester := digest.Canonical.Digester()
+ chunkDigester := digest.Canonical.Digester()
// Now handle the payload, if any
- var startOffset, endOffset int64
+ startOffset := int64(0)
+ lastOffset := int64(0)
+ lastChunkOffset := int64(0)
+
checksum := ""
+
+ chunks := []chunk{}
+
+ hf := &holesFinder{
+ threshold: holesThreshold,
+ reader: bufio.NewReader(tr),
+ }
+
+ rcReader := &rollingChecksumReader{
+ reader: hf,
+ rollsum: NewRollSum(),
+ }
+
+ payloadDest := io.MultiWriter(payloadDigester.Hash(), chunkDigester.Hash(), zstdWriter)
for {
- read, errRead := tr.Read(buf)
+ mustSplit, read, errRead := rcReader.Read(buf)
if errRead != nil && errRead != io.EOF {
return err
}
-
- // restart the compression only if there is
- // a payload.
+ // restart the compression only if there is a payload.
if read > 0 {
if startOffset == 0 {
startOffset, err = restartCompression()
if err != nil {
return err
}
+ lastOffset = startOffset
+ }
+
+ if _, err := payloadDest.Write(buf[:read]); err != nil {
+ return err
}
- _, err := payloadDest.Write(buf[:read])
+ }
+ if (mustSplit || errRead == io.EOF) && startOffset > 0 {
+ off, err := restartCompression()
if err != nil {
return err
}
+
+ chunkSize := rcReader.WrittenOut - lastChunkOffset
+ if chunkSize > 0 {
+ chunkType := internal.ChunkTypeData
+ if rcReader.IsLastChunkZeros {
+ chunkType = internal.ChunkTypeZeros
+ }
+
+ chunks = append(chunks, chunk{
+ ChunkOffset: lastChunkOffset,
+ Offset: lastOffset,
+ Checksum: chunkDigester.Digest().String(),
+ ChunkSize: chunkSize,
+ ChunkType: chunkType,
+ })
+ }
+
+ lastOffset = off
+ lastChunkOffset = rcReader.WrittenOut
+ chunkDigester = digest.Canonical.Digester()
+ payloadDest = io.MultiWriter(payloadDigester.Hash(), chunkDigester.Hash(), zstdWriter)
}
if errRead == io.EOF {
if startOffset > 0 {
- endOffset, err = restartCompression()
- if err != nil {
- return err
- }
checksum = payloadDigester.Digest().String()
}
break
@@ -112,30 +334,42 @@ func writeZstdChunkedStream(destFile io.Writer, outMetadata map[string]string, r
for k, v := range hdr.Xattrs {
xattrs[k] = base64.StdEncoding.EncodeToString([]byte(v))
}
- m := internal.FileMetadata{
- Type: typ,
- Name: hdr.Name,
- Linkname: hdr.Linkname,
- Mode: hdr.Mode,
- Size: hdr.Size,
- UID: hdr.Uid,
- GID: hdr.Gid,
- ModTime: hdr.ModTime,
- AccessTime: hdr.AccessTime,
- ChangeTime: hdr.ChangeTime,
- Devmajor: hdr.Devmajor,
- Devminor: hdr.Devminor,
- Xattrs: xattrs,
- Digest: checksum,
- Offset: startOffset,
- EndOffset: endOffset,
-
- // ChunkSize is 0 for the last chunk
- ChunkSize: 0,
- ChunkOffset: 0,
- ChunkDigest: checksum,
- }
- metadata = append(metadata, m)
+ entries := []internal.FileMetadata{
+ {
+ Type: typ,
+ Name: hdr.Name,
+ Linkname: hdr.Linkname,
+ Mode: hdr.Mode,
+ Size: hdr.Size,
+ UID: hdr.Uid,
+ GID: hdr.Gid,
+ ModTime: &hdr.ModTime,
+ AccessTime: &hdr.AccessTime,
+ ChangeTime: &hdr.ChangeTime,
+ Devmajor: hdr.Devmajor,
+ Devminor: hdr.Devminor,
+ Xattrs: xattrs,
+ Digest: checksum,
+ Offset: startOffset,
+ EndOffset: lastOffset,
+ },
+ }
+ for i := 1; i < len(chunks); i++ {
+ entries = append(entries, internal.FileMetadata{
+ Type: internal.TypeChunk,
+ Name: hdr.Name,
+ ChunkOffset: chunks[i].ChunkOffset,
+ })
+ }
+ if len(chunks) > 1 {
+ for i := range chunks {
+ entries[i].ChunkSize = chunks[i].ChunkSize
+ entries[i].Offset = chunks[i].Offset
+ entries[i].ChunkDigest = chunks[i].Checksum
+ entries[i].ChunkType = chunks[i].ChunkType
+ }
+ }
+ metadata = append(metadata, entries...)
}
rawBytes := tr.RawBytes()
@@ -212,7 +446,7 @@ func zstdChunkedWriterWithLevel(out io.Writer, metadata map[string]string, level
// ZstdCompressor is a CompressorFunc for the zstd compression algorithm.
func ZstdCompressor(r io.Writer, metadata map[string]string, level *int) (io.WriteCloser, error) {
if level == nil {
- l := 3
+ l := 10
level = &l
}
diff --git a/vendor/github.com/containers/storage/pkg/chunked/compressor/rollsum.go b/vendor/github.com/containers/storage/pkg/chunked/compressor/rollsum.go
new file mode 100644
index 000000000..f4dfad822
--- /dev/null
+++ b/vendor/github.com/containers/storage/pkg/chunked/compressor/rollsum.go
@@ -0,0 +1,81 @@
+/*
+Copyright 2011 The Perkeep Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package rollsum implements rolling checksums similar to apenwarr's bup, which
+// is similar to librsync.
+//
+// The bup project is at https://github.com/apenwarr/bup and its splitting in
+// particular is at https://github.com/apenwarr/bup/blob/master/lib/bup/bupsplit.c
+package compressor
+
+import (
+ "math/bits"
+)
+
+const windowSize = 64 // Roll assumes windowSize is a power of 2
+const charOffset = 31
+
+const blobBits = 13
+const blobSize = 1 << blobBits // 8k
+
+type RollSum struct {
+ s1, s2 uint32
+ window [windowSize]uint8
+ wofs int
+}
+
+func NewRollSum() *RollSum {
+ return &RollSum{
+ s1: windowSize * charOffset,
+ s2: windowSize * (windowSize - 1) * charOffset,
+ }
+}
+
+func (rs *RollSum) add(drop, add uint32) {
+ s1 := rs.s1 + add - drop
+ rs.s1 = s1
+ rs.s2 += s1 - uint32(windowSize)*(drop+charOffset)
+}
+
+// Roll adds ch to the rolling sum.
+func (rs *RollSum) Roll(ch byte) {
+ wp := &rs.window[rs.wofs]
+ rs.add(uint32(*wp), uint32(ch))
+ *wp = ch
+ rs.wofs = (rs.wofs + 1) & (windowSize - 1)
+}
+
+// OnSplit reports whether at least 13 consecutive trailing bits of
+// the current checksum are set the same way.
+func (rs *RollSum) OnSplit() bool {
+ return (rs.s2 & (blobSize - 1)) == ((^0) & (blobSize - 1))
+}
+
+// OnSplitWithBits reports whether at least n consecutive trailing bits
+// of the current checksum are set the same way.
+func (rs *RollSum) OnSplitWithBits(n uint32) bool {
+ mask := (uint32(1) << n) - 1
+ return rs.s2&mask == (^uint32(0))&mask
+}
+
+func (rs *RollSum) Bits() int {
+ rsum := rs.Digest() >> (blobBits + 1)
+ return blobBits + bits.TrailingZeros32(^rsum)
+}
+
+func (rs *RollSum) Digest() uint32 {
+ return (rs.s1 << 16) | (rs.s2 & 0xffff)
+}
diff --git a/vendor/github.com/containers/storage/pkg/chunked/internal/compression.go b/vendor/github.com/containers/storage/pkg/chunked/internal/compression.go
index c91c43d85..3bb5286d9 100644
--- a/vendor/github.com/containers/storage/pkg/chunked/internal/compression.go
+++ b/vendor/github.com/containers/storage/pkg/chunked/internal/compression.go
@@ -8,11 +8,11 @@ import (
"archive/tar"
"bytes"
"encoding/binary"
- "encoding/json"
"fmt"
"io"
"time"
+ jsoniter "github.com/json-iterator/go"
"github.com/klauspost/compress/zstd"
"github.com/opencontainers/go-digest"
)
@@ -20,6 +20,9 @@ import (
type TOC struct {
Version int `json:"version"`
Entries []FileMetadata `json:"entries"`
+
+ // internal: used by unmarshalToc
+ StringsBuf bytes.Buffer `json:"-"`
}
type FileMetadata struct {
@@ -27,26 +30,34 @@ type FileMetadata struct {
Name string `json:"name"`
Linkname string `json:"linkName,omitempty"`
Mode int64 `json:"mode,omitempty"`
- Size int64 `json:"size"`
- UID int `json:"uid"`
- GID int `json:"gid"`
- ModTime time.Time `json:"modtime"`
- AccessTime time.Time `json:"accesstime"`
- ChangeTime time.Time `json:"changetime"`
- Devmajor int64 `json:"devMajor"`
- Devminor int64 `json:"devMinor"`
+ Size int64 `json:"size,omitempty"`
+ UID int `json:"uid,omitempty"`
+ GID int `json:"gid,omitempty"`
+ ModTime *time.Time `json:"modtime,omitempty"`
+ AccessTime *time.Time `json:"accesstime,omitempty"`
+ ChangeTime *time.Time `json:"changetime,omitempty"`
+ Devmajor int64 `json:"devMajor,omitempty"`
+ Devminor int64 `json:"devMinor,omitempty"`
Xattrs map[string]string `json:"xattrs,omitempty"`
Digest string `json:"digest,omitempty"`
Offset int64 `json:"offset,omitempty"`
EndOffset int64 `json:"endOffset,omitempty"`
- // Currently chunking is not supported.
ChunkSize int64 `json:"chunkSize,omitempty"`
ChunkOffset int64 `json:"chunkOffset,omitempty"`
ChunkDigest string `json:"chunkDigest,omitempty"`
+ ChunkType string `json:"chunkType,omitempty"`
+
+ // internal: computed by mergeTOCEntries.
+ Chunks []*FileMetadata `json:"-"`
}
const (
+ ChunkTypeData = ""
+ ChunkTypeZeros = "zeros"
+)
+
+const (
TypeReg = "reg"
TypeChunk = "chunk"
TypeLink = "hardlink"
@@ -123,6 +134,7 @@ func WriteZstdChunkedManifest(dest io.Writer, outMetadata map[string]string, off
Entries: metadata,
}
+ var json = jsoniter.ConfigCompatibleWithStandardLibrary
// Generate the manifest
manifest, err := json.Marshal(toc)
if err != nil {
diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
index 52d21d689..92b15c2bf 100644
--- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
+++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
@@ -4,8 +4,8 @@ import (
archivetar "archive/tar"
"context"
"encoding/base64"
- "encoding/json"
"fmt"
+ "hash"
"io"
"io/ioutil"
"os"
@@ -13,6 +13,7 @@ import (
"reflect"
"sort"
"strings"
+ "sync"
"sync/atomic"
"syscall"
"time"
@@ -43,28 +44,35 @@ const (
bigDataKey = "zstd-chunked-manifest"
fileTypeZstdChunked = iota
- fileTypeEstargz = iota
+ fileTypeEstargz
+ fileTypeNoCompression
+ fileTypeHole
+
+ copyGoRoutines = 32
)
type compressedFileType int
type chunkedDiffer struct {
- stream ImageSourceSeekable
- manifest []byte
- layersMetadata map[string][]internal.FileMetadata
- layersTarget map[string]string
- tocOffset int64
- fileType compressedFileType
+ stream ImageSourceSeekable
+ manifest []byte
+ layersCache *layersCache
+ tocOffset int64
+ fileType compressedFileType
+
+ copyBuffer []byte
gzipReader *pgzip.Reader
+ zstdReader *zstd.Decoder
+ rawReader io.Reader
}
var xattrsToIgnore = map[string]interface{}{
"security.selinux": true,
}
-func timeToTimespec(time time.Time) (ts unix.Timespec) {
- if time.IsZero() {
+func timeToTimespec(time *time.Time) (ts unix.Timespec) {
+ if time == nil || time.IsZero() {
// Return UTIME_OMIT special value
ts.Sec = 0
ts.Nsec = ((1 << 30) - 2)
@@ -128,54 +136,6 @@ func copyFileContent(srcFd int, destFile string, dirfd int, mode os.FileMode, us
return dstFile, st.Size(), nil
}
-func prepareOtherLayersCache(layersMetadata map[string][]internal.FileMetadata) map[string]map[string][]*internal.FileMetadata {
- maps := make(map[string]map[string][]*internal.FileMetadata)
-
- for layerID, v := range layersMetadata {
- r := make(map[string][]*internal.FileMetadata)
- for i := range v {
- if v[i].Digest != "" {
- r[v[i].Digest] = append(r[v[i].Digest], &v[i])
- }
- }
- maps[layerID] = r
- }
- return maps
-}
-
-func getLayersCache(store storage.Store) (map[string][]internal.FileMetadata, map[string]string, error) {
- allLayers, err := store.Layers()
- if err != nil {
- return nil, nil, err
- }
-
- layersMetadata := make(map[string][]internal.FileMetadata)
- layersTarget := make(map[string]string)
- for _, r := range allLayers {
- manifestReader, err := store.LayerBigData(r.ID, bigDataKey)
- if err != nil {
- continue
- }
- defer manifestReader.Close()
- manifest, err := ioutil.ReadAll(manifestReader)
- if err != nil {
- return nil, nil, fmt.Errorf("open manifest file for layer %q: %w", r.ID, err)
- }
- var toc internal.TOC
- if err := json.Unmarshal(manifest, &toc); err != nil {
- continue
- }
- layersMetadata[r.ID] = toc.Entries
- target, err := store.DifferTarget(r.ID)
- if err != nil {
- return nil, nil, fmt.Errorf("get checkout directory layer %q: %w", r.ID, err)
- }
- layersTarget[r.ID] = target
- }
-
- return layersMetadata, layersTarget, nil
-}
-
// GetDiffer returns a differ than can be used with ApplyDiffWithDiffer.
func GetDiffer(ctx context.Context, store storage.Store, blobSize int64, annotations map[string]string, iss ImageSourceSeekable) (graphdriver.Differ, error) {
if _, ok := annotations[internal.ManifestChecksumKey]; ok {
@@ -192,18 +152,18 @@ func makeZstdChunkedDiffer(ctx context.Context, store storage.Store, blobSize in
if err != nil {
return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
}
- layersMetadata, layersTarget, err := getLayersCache(store)
+ layersCache, err := getLayersCache(store)
if err != nil {
return nil, err
}
return &chunkedDiffer{
- stream: iss,
- manifest: manifest,
- layersMetadata: layersMetadata,
- layersTarget: layersTarget,
- tocOffset: tocOffset,
- fileType: fileTypeZstdChunked,
+ copyBuffer: makeCopyBuffer(),
+ stream: iss,
+ manifest: manifest,
+ layersCache: layersCache,
+ tocOffset: tocOffset,
+ fileType: fileTypeZstdChunked,
}, nil
}
@@ -212,37 +172,41 @@ func makeEstargzChunkedDiffer(ctx context.Context, store storage.Store, blobSize
if err != nil {
return nil, fmt.Errorf("read zstd:chunked manifest: %w", err)
}
- layersMetadata, layersTarget, err := getLayersCache(store)
+ layersCache, err := getLayersCache(store)
if err != nil {
return nil, err
}
return &chunkedDiffer{
- stream: iss,
- manifest: manifest,
- layersMetadata: layersMetadata,
- layersTarget: layersTarget,
- tocOffset: tocOffset,
- fileType: fileTypeEstargz,
+ copyBuffer: makeCopyBuffer(),
+ stream: iss,
+ manifest: manifest,
+ layersCache: layersCache,
+ tocOffset: tocOffset,
+ fileType: fileTypeEstargz,
}, nil
}
+func makeCopyBuffer() []byte {
+ return make([]byte, 2<<20)
+}
+
// copyFileFromOtherLayer copies a file from another layer
// file is the file to look for.
// source is the path to the source layer checkout.
-// otherFile contains the metadata for the file.
+// name is the path to the file to copy in source.
// dirfd is an open file descriptor to the destination root directory.
// useHardLinks defines whether the deduplication can be performed using hard links.
-func copyFileFromOtherLayer(file *internal.FileMetadata, source string, otherFile *internal.FileMetadata, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
+func copyFileFromOtherLayer(file *internal.FileMetadata, source string, name string, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
srcDirfd, err := unix.Open(source, unix.O_RDONLY, 0)
if err != nil {
- return false, nil, 0, fmt.Errorf("open source file %q: %w", source, err)
+ return false, nil, 0, fmt.Errorf("open source file: %w", err)
}
defer unix.Close(srcDirfd)
- srcFile, err := openFileUnderRoot(otherFile.Name, srcDirfd, unix.O_RDONLY, 0)
+ srcFile, err := openFileUnderRoot(name, srcDirfd, unix.O_RDONLY, 0)
if err != nil {
- return false, nil, 0, fmt.Errorf("open source file %q under target rootfs: %w", otherFile.Name, err)
+ return false, nil, 0, fmt.Errorf("open source file under target rootfs: %w", err)
}
defer srcFile.Close()
@@ -308,45 +272,9 @@ func canDedupFileWithHardLink(file *internal.FileMetadata, fd int, s os.FileInfo
return canDedupMetadataWithHardLink(file, &otherFile)
}
-// findFileInOtherLayers finds the specified file in other layers.
-// file is the file to look for.
-// dirfd is an open file descriptor to the checkout root directory.
-// layersMetadata contains the metadata for each layer in the storage.
-// layersTarget maps each layer to its checkout on disk.
-// useHardLinks defines whether the deduplication can be performed using hard links.
-func findFileInOtherLayers(file *internal.FileMetadata, dirfd int, layersMetadata map[string]map[string][]*internal.FileMetadata, layersTarget map[string]string, useHardLinks bool) (bool, *os.File, int64, error) {
- // this is ugly, needs to be indexed
- for layerID, checksums := range layersMetadata {
- source, ok := layersTarget[layerID]
- if !ok {
- continue
- }
- files, found := checksums[file.Digest]
- if !found {
- continue
- }
- for _, candidate := range files {
- // check if it is a valid candidate to dedup file
- if useHardLinks && !canDedupMetadataWithHardLink(file, candidate) {
- continue
- }
-
- found, dstFile, written, err := copyFileFromOtherLayer(file, source, candidate, dirfd, useHardLinks)
- if found && err == nil {
- return found, dstFile, written, err
- }
- }
- }
- // If hard links deduplication was used and it has failed, try again without hard links.
- if useHardLinks {
- return findFileInOtherLayers(file, dirfd, layersMetadata, layersTarget, false)
- }
- return false, nil, 0, nil
-}
-
-func getFileDigest(f *os.File) (digest.Digest, error) {
+func getFileDigest(f *os.File, buf []byte) (digest.Digest, error) {
digester := digest.Canonical.Digester()
- if _, err := io.Copy(digester.Hash(), f); err != nil {
+ if _, err := io.CopyBuffer(digester.Hash(), f, buf); err != nil {
return "", err
}
return digester.Digest(), nil
@@ -408,7 +336,7 @@ func findFileInOSTreeRepos(file *internal.FileMetadata, ostreeRepos []string, di
// file is the file to look for.
// dirfd is an open fd to the destination checkout.
// useHardLinks defines whether the deduplication can be performed using hard links.
-func findFileOnTheHost(file *internal.FileMetadata, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
+func findFileOnTheHost(file *internal.FileMetadata, dirfd int, useHardLinks bool, buf []byte) (bool, *os.File, int64, error) {
sourceFile := filepath.Clean(filepath.Join("/", file.Name))
if !strings.HasPrefix(sourceFile, "/usr/") {
// limit host deduplication to files under /usr.
@@ -437,7 +365,7 @@ func findFileOnTheHost(file *internal.FileMetadata, dirfd int, useHardLinks bool
return false, nil, 0, err
}
- checksum, err := getFileDigest(f)
+ checksum, err := getFileDigest(f, buf)
if err != nil {
return false, nil, 0, err
}
@@ -459,7 +387,7 @@ func findFileOnTheHost(file *internal.FileMetadata, dirfd int, useHardLinks bool
dstFile.Close()
return false, nil, 0, err
}
- checksum, err = getFileDigest(f)
+ checksum, err = getFileDigest(f, buf)
if err != nil {
dstFile.Close()
return false, nil, 0, err
@@ -471,6 +399,19 @@ func findFileOnTheHost(file *internal.FileMetadata, dirfd int, useHardLinks bool
return true, dstFile, written, nil
}
+// findFileInOtherLayers finds the specified file in other layers.
+// cache is the layers cache to use.
+// file is the file to look for.
+// dirfd is an open file descriptor to the checkout root directory.
+// useHardLinks defines whether the deduplication can be performed using hard links.
+func findFileInOtherLayers(cache *layersCache, file *internal.FileMetadata, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
+ target, name, err := cache.findFileInOtherLayers(file, useHardLinks)
+ if err != nil || name == "" {
+ return false, nil, 0, err
+ }
+ return copyFileFromOtherLayer(file, target, name, dirfd, useHardLinks)
+}
+
func maybeDoIDRemap(manifest []internal.FileMetadata, options *archive.TarOptions) error {
if options.ChownOpts == nil && len(options.UIDMaps) == 0 || len(options.GIDMaps) == 0 {
return nil
@@ -497,18 +438,46 @@ func maybeDoIDRemap(manifest []internal.FileMetadata, options *archive.TarOption
return nil
}
-type missingFile struct {
- File *internal.FileMetadata
+type originFile struct {
+ Root string
+ Path string
+ Offset int64
+}
+
+type missingFileChunk struct {
Gap int64
+ Hole bool
+
+ File *internal.FileMetadata
+
+ CompressedSize int64
+ UncompressedSize int64
}
-func (m missingFile) Length() int64 {
- return m.File.EndOffset - m.File.Offset
+type missingPart struct {
+ Hole bool
+ SourceChunk *ImageSourceChunk
+ OriginFile *originFile
+ Chunks []missingFileChunk
}
-type missingChunk struct {
- RawChunk ImageSourceChunk
- Files []missingFile
+func (o *originFile) OpenFile() (io.ReadCloser, error) {
+ srcDirfd, err := unix.Open(o.Root, unix.O_RDONLY, 0)
+ if err != nil {
+ return nil, fmt.Errorf("open source file: %w", err)
+ }
+ defer unix.Close(srcDirfd)
+
+ srcFile, err := openFileUnderRoot(o.Path, srcDirfd, unix.O_RDONLY, 0)
+ if err != nil {
+ return nil, fmt.Errorf("open source file under target rootfs: %w", err)
+ }
+
+ if _, err := srcFile.Seek(o.Offset, 0); err != nil {
+ srcFile.Close()
+ return nil, err
+ }
+ return srcFile, nil
}
// setFileAttrs sets the file attributes for file given metadata
@@ -711,7 +680,7 @@ func openFileUnderRoot(name string, dirfd int, flags uint64, mode os.FileMode) (
newDirfd, err2 := openOrCreateDirUnderRoot(parent, dirfd, 0)
if err2 == nil {
defer newDirfd.Close()
- fd, err := openFileUnderRootRaw(dirfd, name, flags, mode)
+ fd, err := openFileUnderRootRaw(int(newDirfd.Fd()), filepath.Base(name), flags, mode)
if err == nil {
return os.NewFile(uintptr(fd), name), nil
}
@@ -755,159 +724,367 @@ func openOrCreateDirUnderRoot(name string, dirfd int, mode os.FileMode) (*os.Fil
return nil, err
}
-func (c *chunkedDiffer) createFileFromCompressedStream(dest string, dirfd int, reader io.Reader, mode os.FileMode, metadata *internal.FileMetadata, options *archive.TarOptions) (err error) {
- file, err := openFileUnderRoot(metadata.Name, dirfd, newFileFlags, 0)
- if err != nil {
- return err
+func (c *chunkedDiffer) prepareCompressedStreamToFile(partCompression compressedFileType, from io.Reader, mf *missingFileChunk) (compressedFileType, error) {
+ switch {
+ case partCompression == fileTypeHole:
+ // The entire part is a hole. Do not need to read from a file.
+ c.rawReader = nil
+ return fileTypeHole, nil
+ case mf.Hole:
+ // Only the missing chunk in the requested part refers to a hole.
+ // The received data must be discarded.
+ limitReader := io.LimitReader(from, mf.CompressedSize)
+ _, err := io.CopyBuffer(ioutil.Discard, limitReader, c.copyBuffer)
+ return fileTypeHole, err
+ case partCompression == fileTypeZstdChunked:
+ c.rawReader = io.LimitReader(from, mf.CompressedSize)
+ if c.zstdReader == nil {
+ r, err := zstd.NewReader(c.rawReader)
+ if err != nil {
+ return partCompression, err
+ }
+ c.zstdReader = r
+ } else {
+ if err := c.zstdReader.Reset(c.rawReader); err != nil {
+ return partCompression, err
+ }
+ }
+ case partCompression == fileTypeEstargz:
+ c.rawReader = io.LimitReader(from, mf.CompressedSize)
+ if c.gzipReader == nil {
+ r, err := pgzip.NewReader(c.rawReader)
+ if err != nil {
+ return partCompression, err
+ }
+ c.gzipReader = r
+ } else {
+ if err := c.gzipReader.Reset(c.rawReader); err != nil {
+ return partCompression, err
+ }
+ }
+ case partCompression == fileTypeNoCompression:
+ c.rawReader = io.LimitReader(from, mf.UncompressedSize)
+ default:
+ return partCompression, fmt.Errorf("unknown file type %q", c.fileType)
}
- defer func() {
- err2 := file.Close()
- if err == nil {
- err = err2
+ return partCompression, nil
+}
+
+// hashHole writes SIZE zeros to the specified hasher
+func hashHole(h hash.Hash, size int64, copyBuffer []byte) error {
+ count := int64(len(copyBuffer))
+ if size < count {
+ count = size
+ }
+ for i := int64(0); i < count; i++ {
+ copyBuffer[i] = 0
+ }
+ for size > 0 {
+ count = int64(len(copyBuffer))
+ if size < count {
+ count = size
}
- }()
+ if _, err := h.Write(copyBuffer[:count]); err != nil {
+ return err
+ }
+ size -= count
+ }
+ return nil
+}
- digester := digest.Canonical.Digester()
- checksum := digester.Hash()
- to := io.MultiWriter(file, checksum)
+// appendHole creates a hole with the specified size at the open fd.
+func appendHole(fd int, size int64) error {
+ off, err := unix.Seek(fd, size, unix.SEEK_CUR)
+ if err != nil {
+ return err
+ }
+ // Make sure the file size is changed. It might be the last hole and no other data written afterwards.
+ if err := unix.Ftruncate(fd, off); err != nil {
+ return err
+ }
+ return nil
+}
- switch c.fileType {
+func (c *chunkedDiffer) appendCompressedStreamToFile(compression compressedFileType, destFile *destinationFile, size int64) error {
+ switch compression {
case fileTypeZstdChunked:
- z, err := zstd.NewReader(reader)
- if err != nil {
+ defer c.zstdReader.Reset(nil)
+ if _, err := io.CopyBuffer(destFile.to, io.LimitReader(c.zstdReader, size), c.copyBuffer); err != nil {
return err
}
- defer z.Close()
-
- if _, err := io.Copy(to, io.LimitReader(z, metadata.Size)); err != nil {
+ case fileTypeEstargz:
+ defer c.gzipReader.Close()
+ if _, err := io.CopyBuffer(destFile.to, io.LimitReader(c.gzipReader, size), c.copyBuffer); err != nil {
return err
}
- if _, err := io.Copy(ioutil.Discard, reader); err != nil {
+ case fileTypeNoCompression:
+ if _, err := io.CopyBuffer(destFile.to, io.LimitReader(c.rawReader, size), c.copyBuffer); err != nil {
return err
}
- case fileTypeEstargz:
- if c.gzipReader == nil {
- r, err := pgzip.NewReader(reader)
- if err != nil {
- return err
- }
- c.gzipReader = r
- } else {
- if err := c.gzipReader.Reset(reader); err != nil {
- return err
- }
- }
- defer c.gzipReader.Close()
-
- if _, err := io.Copy(to, io.LimitReader(c.gzipReader, metadata.Size)); err != nil {
+ case fileTypeHole:
+ if err := appendHole(int(destFile.file.Fd()), size); err != nil {
return err
}
- if _, err := io.Copy(ioutil.Discard, reader); err != nil {
+ if err := hashHole(destFile.hash, size, c.copyBuffer); err != nil {
return err
}
default:
return fmt.Errorf("unknown file type %q", c.fileType)
}
+ return nil
+}
+
+type destinationFile struct {
+ dirfd int
+ file *os.File
+ digester digest.Digester
+ hash hash.Hash
+ to io.Writer
+ metadata *internal.FileMetadata
+ options *archive.TarOptions
+}
+
+func openDestinationFile(dirfd int, metadata *internal.FileMetadata, options *archive.TarOptions) (*destinationFile, error) {
+ file, err := openFileUnderRoot(metadata.Name, dirfd, newFileFlags, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ digester := digest.Canonical.Digester()
+ hash := digester.Hash()
+ to := io.MultiWriter(file, hash)
+
+ return &destinationFile{
+ file: file,
+ digester: digester,
+ hash: hash,
+ to: to,
+ metadata: metadata,
+ options: options,
+ dirfd: dirfd,
+ }, nil
+}
- manifestChecksum, err := digest.Parse(metadata.Digest)
+func (d *destinationFile) Close() error {
+ manifestChecksum, err := digest.Parse(d.metadata.Digest)
if err != nil {
return err
}
- if digester.Digest() != manifestChecksum {
- return fmt.Errorf("checksum mismatch for %q", dest)
+ if d.digester.Digest() != manifestChecksum {
+ return fmt.Errorf("checksum mismatch for %q (got %q instead of %q)", d.file.Name(), d.digester.Digest(), manifestChecksum)
}
- return setFileAttrs(dirfd, file, mode, metadata, options, false)
+
+ return setFileAttrs(d.dirfd, d.file, os.FileMode(d.metadata.Mode), d.metadata, d.options, false)
}
-func (c *chunkedDiffer) storeMissingFiles(streams chan io.ReadCloser, errs chan error, dest string, dirfd int, missingChunks []missingChunk, options *archive.TarOptions) error {
- for mc := 0; ; mc++ {
- var part io.ReadCloser
- select {
- case p := <-streams:
- part = p
- case err := <-errs:
- return err
- }
- if part == nil {
- if mc == len(missingChunks) {
- break
+func closeDestinationFiles(files chan *destinationFile, errors chan error) {
+ for f := range files {
+ errors <- f.Close()
+ }
+ close(errors)
+}
+
+func (c *chunkedDiffer) storeMissingFiles(streams chan io.ReadCloser, errs chan error, dest string, dirfd int, missingParts []missingPart, options *archive.TarOptions) (Err error) {
+ var destFile *destinationFile
+
+ filesToClose := make(chan *destinationFile, 3)
+ closeFilesErrors := make(chan error, 2)
+
+ go closeDestinationFiles(filesToClose, closeFilesErrors)
+ defer func() {
+ close(filesToClose)
+ for e := range closeFilesErrors {
+ if e != nil && Err == nil {
+ Err = e
}
- return errors.Errorf("invalid stream returned")
}
- if mc == len(missingChunks) {
- part.Close()
- return errors.Errorf("too many chunks returned")
+ }()
+
+ for _, missingPart := range missingParts {
+ var part io.ReadCloser
+ partCompression := c.fileType
+ switch {
+ case missingPart.Hole:
+ partCompression = fileTypeHole
+ case missingPart.OriginFile != nil:
+ var err error
+ part, err = missingPart.OriginFile.OpenFile()
+ if err != nil {
+ return err
+ }
+ partCompression = fileTypeNoCompression
+ case missingPart.SourceChunk != nil:
+ select {
+ case p := <-streams:
+ part = p
+ case err := <-errs:
+ return err
+ }
+ if part == nil {
+ return errors.Errorf("invalid stream returned")
+ }
+ default:
+ return errors.Errorf("internal error: missing part misses both local and remote data stream")
}
- for _, mf := range missingChunks[mc].Files {
+ for _, mf := range missingPart.Chunks {
if mf.Gap > 0 {
limitReader := io.LimitReader(part, mf.Gap)
- _, err := io.Copy(ioutil.Discard, limitReader)
+ _, err := io.CopyBuffer(ioutil.Discard, limitReader, c.copyBuffer)
if err != nil {
- part.Close()
- return err
+ Err = err
+ goto exit
}
continue
}
- limitReader := io.LimitReader(part, mf.Length())
+ if mf.File.Name == "" {
+ Err = errors.Errorf("file name empty")
+ goto exit
+ }
- if err := c.createFileFromCompressedStream(dest, dirfd, limitReader, os.FileMode(mf.File.Mode), mf.File, options); err != nil {
- part.Close()
- return err
+ compression, err := c.prepareCompressedStreamToFile(partCompression, part, &mf)
+ if err != nil {
+ Err = err
+ goto exit
+ }
+
+ // Open the new file if it is different that what is already
+ // opened
+ if destFile == nil || destFile.metadata.Name != mf.File.Name {
+ var err error
+ if destFile != nil {
+ cleanup:
+ for {
+ select {
+ case err = <-closeFilesErrors:
+ if err != nil {
+ Err = err
+ goto exit
+ }
+ default:
+ break cleanup
+ }
+ }
+ filesToClose <- destFile
+ }
+ destFile, err = openDestinationFile(dirfd, mf.File, options)
+ if err != nil {
+ Err = err
+ goto exit
+ }
+ }
+
+ if err := c.appendCompressedStreamToFile(compression, destFile, mf.UncompressedSize); err != nil {
+ Err = err
+ goto exit
+ }
+ if c.rawReader != nil {
+ if _, err := io.CopyBuffer(ioutil.Discard, c.rawReader, c.copyBuffer); err != nil {
+ Err = err
+ goto exit
+ }
+ }
+ }
+ exit:
+ if part != nil {
+ part.Close()
+ if Err != nil {
+ break
}
}
- part.Close()
}
+
+ if destFile != nil {
+ return destFile.Close()
+ }
+
return nil
}
-func mergeMissingChunks(missingChunks []missingChunk, target int) []missingChunk {
- if len(missingChunks) <= target {
- return missingChunks
+func mergeMissingChunks(missingParts []missingPart, target int) []missingPart {
+ getGap := func(missingParts []missingPart, i int) int {
+ prev := missingParts[i-1].SourceChunk.Offset + missingParts[i-1].SourceChunk.Length
+ return int(missingParts[i].SourceChunk.Offset - prev)
+ }
+ getCost := func(missingParts []missingPart, i int) int {
+ cost := getGap(missingParts, i)
+ if missingParts[i-1].OriginFile != nil {
+ cost += int(missingParts[i-1].SourceChunk.Length)
+ }
+ if missingParts[i].OriginFile != nil {
+ cost += int(missingParts[i].SourceChunk.Length)
+ }
+ return cost
+ }
+
+ // simple case: merge chunks from the same file.
+ newMissingParts := missingParts[0:1]
+ prevIndex := 0
+ for i := 1; i < len(missingParts); i++ {
+ gap := getGap(missingParts, i)
+ if gap == 0 && missingParts[prevIndex].OriginFile == nil &&
+ missingParts[i].OriginFile == nil &&
+ !missingParts[prevIndex].Hole && !missingParts[i].Hole &&
+ len(missingParts[prevIndex].Chunks) == 1 && len(missingParts[i].Chunks) == 1 &&
+ missingParts[prevIndex].Chunks[0].File.Name == missingParts[i].Chunks[0].File.Name {
+ missingParts[prevIndex].SourceChunk.Length += uint64(gap) + missingParts[i].SourceChunk.Length
+ missingParts[prevIndex].Chunks[0].CompressedSize += missingParts[i].Chunks[0].CompressedSize
+ missingParts[prevIndex].Chunks[0].UncompressedSize += missingParts[i].Chunks[0].UncompressedSize
+ } else {
+ newMissingParts = append(newMissingParts, missingParts[i])
+ prevIndex++
+ }
}
+ missingParts = newMissingParts
- getGap := func(missingChunks []missingChunk, i int) int {
- prev := missingChunks[i-1].RawChunk.Offset + missingChunks[i-1].RawChunk.Length
- return int(missingChunks[i].RawChunk.Offset - prev)
+ if len(missingParts) <= target {
+ return missingParts
}
// this implementation doesn't account for duplicates, so it could merge
// more than necessary to reach the specified target. Since target itself
// is a heuristic value, it doesn't matter.
- var gaps []int
- for i := 1; i < len(missingChunks); i++ {
- gaps = append(gaps, getGap(missingChunks, i))
+ costs := make([]int, len(missingParts)-1)
+ for i := 1; i < len(missingParts); i++ {
+ costs[i-1] = getCost(missingParts, i)
}
- sort.Ints(gaps)
+ sort.Ints(costs)
- toShrink := len(missingChunks) - target
- targetValue := gaps[toShrink-1]
+ toShrink := len(missingParts) - target
+ if toShrink >= len(costs) {
+ toShrink = len(costs) - 1
+ }
+ targetValue := costs[toShrink]
- newMissingChunks := missingChunks[0:1]
- for i := 1; i < len(missingChunks); i++ {
- gap := getGap(missingChunks, i)
- if gap > targetValue {
- newMissingChunks = append(newMissingChunks, missingChunks[i])
+ newMissingParts = missingParts[0:1]
+ for i := 1; i < len(missingParts); i++ {
+ if getCost(missingParts, i) > targetValue {
+ newMissingParts = append(newMissingParts, missingParts[i])
} else {
- prev := &newMissingChunks[len(newMissingChunks)-1]
- prev.RawChunk.Length += uint64(gap) + missingChunks[i].RawChunk.Length
+ gap := getGap(missingParts, i)
+ prev := &newMissingParts[len(newMissingParts)-1]
+ prev.SourceChunk.Length += uint64(gap) + missingParts[i].SourceChunk.Length
+ prev.Hole = false
+ prev.OriginFile = nil
if gap > 0 {
- gapFile := missingFile{
+ gapFile := missingFileChunk{
Gap: int64(gap),
}
- prev.Files = append(prev.Files, gapFile)
+ prev.Chunks = append(prev.Chunks, gapFile)
}
- prev.Files = append(prev.Files, missingChunks[i].Files...)
+ prev.Chunks = append(prev.Chunks, missingParts[i].Chunks...)
}
}
- return newMissingChunks
+ return newMissingParts
}
-func (c *chunkedDiffer) retrieveMissingFiles(dest string, dirfd int, missingChunks []missingChunk, options *archive.TarOptions) error {
+func (c *chunkedDiffer) retrieveMissingFiles(dest string, dirfd int, missingParts []missingPart, options *archive.TarOptions) error {
var chunksToRequest []ImageSourceChunk
- for _, c := range missingChunks {
- chunksToRequest = append(chunksToRequest, c.RawChunk)
+ for _, c := range missingParts {
+ if c.OriginFile == nil && !c.Hole {
+ chunksToRequest = append(chunksToRequest, *c.SourceChunk)
+ }
}
// There are some missing files. Prepare a multirange request for the missing chunks.
@@ -921,20 +1098,20 @@ func (c *chunkedDiffer) retrieveMissingFiles(dest string, dirfd int, missingChun
}
if _, ok := err.(ErrBadRequest); ok {
- requested := len(missingChunks)
+ requested := len(missingParts)
// If the server cannot handle at least 64 chunks in a single request, just give up.
if requested < 64 {
return err
}
// Merge more chunks to request
- missingChunks = mergeMissingChunks(missingChunks, requested/2)
+ missingParts = mergeMissingChunks(missingParts, requested/2)
continue
}
return err
}
- if err := c.storeMissingFiles(streams, errs, dest, dirfd, missingChunks, options); err != nil {
+ if err := c.storeMissingFiles(streams, errs, dest, dirfd, missingParts, options); err != nil {
return err
}
return nil
@@ -960,7 +1137,7 @@ func safeMkdir(dirfd int, mode os.FileMode, name string, metadata *internal.File
}
}
- file, err := openFileUnderRoot(name, dirfd, unix.O_DIRECTORY|unix.O_RDONLY, 0)
+ file, err := openFileUnderRoot(base, parentFd, unix.O_DIRECTORY|unix.O_RDONLY, 0)
if err != nil {
return err
}
@@ -1109,7 +1286,69 @@ func parseBooleanPullOption(storeOpts *storage.StoreOptions, name string, def bo
return def
}
+type findAndCopyFileOptions struct {
+ useHardLinks bool
+ enableHostDedup bool
+ ostreeRepos []string
+ options *archive.TarOptions
+}
+
+func (c *chunkedDiffer) findAndCopyFile(dirfd int, r *internal.FileMetadata, copyOptions *findAndCopyFileOptions, mode os.FileMode) (bool, error) {
+ finalizeFile := func(dstFile *os.File) error {
+ if dstFile != nil {
+ defer dstFile.Close()
+ if err := setFileAttrs(dirfd, dstFile, mode, r, copyOptions.options, false); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ found, dstFile, _, err := findFileInOtherLayers(c.layersCache, r, dirfd, copyOptions.useHardLinks)
+ if err != nil {
+ return false, err
+ }
+ if found {
+ if err := finalizeFile(dstFile); err != nil {
+ return false, err
+ }
+ return true, nil
+ }
+
+ found, dstFile, _, err = findFileInOSTreeRepos(r, copyOptions.ostreeRepos, dirfd, copyOptions.useHardLinks)
+ if err != nil {
+ return false, err
+ }
+ if found {
+ if err := finalizeFile(dstFile); err != nil {
+ return false, err
+ }
+ return true, nil
+ }
+
+ if copyOptions.enableHostDedup {
+ found, dstFile, _, err = findFileOnTheHost(r, dirfd, copyOptions.useHardLinks, c.copyBuffer)
+ if err != nil {
+ return false, err
+ }
+ if found {
+ if err := finalizeFile(dstFile); err != nil {
+ return false, err
+ }
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (graphdriver.DriverWithDifferOutput, error) {
+ defer c.layersCache.release()
+ defer func() {
+ if c.zstdReader != nil {
+ c.zstdReader.Close()
+ }
+ }()
+
bigData := map[string][]byte{
bigDataKey: c.manifest,
}
@@ -1137,14 +1376,14 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
ostreeRepos := strings.Split(storeOpts.PullOptions["ostree_repos"], ":")
// Generate the manifest
- var toc internal.TOC
- if err := json.Unmarshal(c.manifest, &toc); err != nil {
+ toc, err := unmarshalToc(c.manifest)
+ if err != nil {
return output, err
}
whiteoutConverter := archive.GetWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData)
- var missingChunks []missingChunk
+ var missingParts []missingPart
mergedEntries, err := c.mergeTocEntries(c.fileType, toc.Entries)
if err != nil {
@@ -1170,13 +1409,57 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
}
defer unix.Close(dirfd)
- otherLayersCache := prepareOtherLayersCache(c.layersMetadata)
-
// hardlinks can point to missing files. So create them after all files
// are retrieved
var hardLinks []hardLinkToCreate
- missingChunksSize, totalChunksSize := int64(0), int64(0)
+ missingPartsSize, totalChunksSize := int64(0), int64(0)
+
+ copyOptions := findAndCopyFileOptions{
+ useHardLinks: useHardLinks,
+ enableHostDedup: enableHostDedup,
+ ostreeRepos: ostreeRepos,
+ options: options,
+ }
+
+ type copyFileJob struct {
+ njob int
+ index int
+ mode os.FileMode
+ metadata *internal.FileMetadata
+
+ found bool
+ err error
+ }
+
+ var wg sync.WaitGroup
+
+ copyResults := make([]copyFileJob, len(mergedEntries))
+
+ copyFileJobs := make(chan copyFileJob)
+ defer func() {
+ if copyFileJobs != nil {
+ close(copyFileJobs)
+ }
+ wg.Wait()
+ }()
+
+ for i := 0; i < copyGoRoutines; i++ {
+ wg.Add(1)
+ jobs := copyFileJobs
+
+ go func() {
+ defer wg.Done()
+ for job := range jobs {
+ found, err := c.findAndCopyFile(dirfd, job.metadata, &copyOptions, job.mode)
+ job.err = err
+ job.found = found
+ copyResults[job.njob] = job
+ }
+ }()
+ }
+
+ filesToWaitFor := 0
for i, r := range mergedEntries {
if options.ForceMask != nil {
value := fmt.Sprintf("%d:%d:0%o", r.UID, r.GID, r.Mode&07777)
@@ -1272,74 +1555,95 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
totalChunksSize += r.Size
- finalizeFile := func(dstFile *os.File) error {
- if dstFile != nil {
- defer dstFile.Close()
- if err := setFileAttrs(dirfd, dstFile, mode, &r, options, false); err != nil {
- return err
- }
+ if t == tar.TypeReg {
+ index := i
+ njob := filesToWaitFor
+ job := copyFileJob{
+ mode: mode,
+ metadata: &mergedEntries[index],
+ index: index,
+ njob: njob,
}
- return nil
+ copyFileJobs <- job
+ filesToWaitFor++
}
+ }
- found, dstFile, _, err := findFileInOtherLayers(&r, dirfd, otherLayersCache, c.layersTarget, useHardLinks)
- if err != nil {
- return output, err
- }
- if found {
- if err := finalizeFile(dstFile); err != nil {
- return output, err
- }
- continue
- }
+ close(copyFileJobs)
+ copyFileJobs = nil
- found, dstFile, _, err = findFileInOSTreeRepos(&r, ostreeRepos, dirfd, useHardLinks)
- if err != nil {
- return output, err
+ wg.Wait()
+
+ for _, res := range copyResults[:filesToWaitFor] {
+ if res.err != nil {
+ return output, res.err
}
- if found {
- if err := finalizeFile(dstFile); err != nil {
- return output, err
- }
+ // the file was already copied to its destination
+ // so nothing left to do.
+ if res.found {
continue
}
- if enableHostDedup {
- found, dstFile, _, err = findFileOnTheHost(&r, dirfd, useHardLinks)
- if err != nil {
- return output, err
- }
- if found {
- if err := finalizeFile(dstFile); err != nil {
- return output, err
- }
- continue
+ r := &mergedEntries[res.index]
+
+ missingPartsSize += r.Size
+
+ remainingSize := r.Size
+
+ // the file is missing, attempt to find individual chunks.
+ for _, chunk := range r.Chunks {
+ compressedSize := int64(chunk.EndOffset - chunk.Offset)
+ size := remainingSize
+ if chunk.ChunkSize > 0 {
+ size = chunk.ChunkSize
}
- }
+ remainingSize = remainingSize - size
- missingChunksSize += r.Size
- if t == tar.TypeReg {
rawChunk := ImageSourceChunk{
- Offset: uint64(r.Offset),
- Length: uint64(r.EndOffset - r.Offset),
+ Offset: uint64(chunk.Offset),
+ Length: uint64(compressedSize),
}
-
- file := missingFile{
- File: &mergedEntries[i],
+ file := missingFileChunk{
+ File: &mergedEntries[res.index],
+ CompressedSize: compressedSize,
+ UncompressedSize: size,
}
-
- missingChunks = append(missingChunks, missingChunk{
- RawChunk: rawChunk,
- Files: []missingFile{
+ mp := missingPart{
+ SourceChunk: &rawChunk,
+ Chunks: []missingFileChunk{
file,
},
- })
+ }
+
+ switch chunk.ChunkType {
+ case internal.ChunkTypeData:
+ root, path, offset, err := c.layersCache.findChunkInOtherLayers(chunk)
+ if err != nil {
+ return output, err
+ }
+ if offset >= 0 && validateChunkChecksum(chunk, root, path, offset, c.copyBuffer) {
+ missingPartsSize -= size
+ mp.OriginFile = &originFile{
+ Root: root,
+ Path: path,
+ Offset: offset,
+ }
+ }
+ case internal.ChunkTypeZeros:
+ missingPartsSize -= size
+ mp.Hole = true
+ // Mark all chunks belonging to the missing part as holes
+ for i := range mp.Chunks {
+ mp.Chunks[i].Hole = true
+ }
+ }
+ missingParts = append(missingParts, mp)
}
}
// There are some missing files. Prepare a multirange request for the missing chunks.
- if len(missingChunks) > 0 {
- missingChunks = mergeMissingChunks(missingChunks, maxNumberMissingChunks)
- if err := c.retrieveMissingFiles(dest, dirfd, missingChunks, options); err != nil {
+ if len(missingParts) > 0 {
+ missingParts = mergeMissingChunks(missingParts, maxNumberMissingChunks)
+ if err := c.retrieveMissingFiles(dest, dirfd, missingParts, options); err != nil {
return output, err
}
}
@@ -1351,31 +1655,69 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
}
if totalChunksSize > 0 {
- logrus.Debugf("Missing %d bytes out of %d (%.2f %%)", missingChunksSize, totalChunksSize, float32(missingChunksSize*100.0)/float32(totalChunksSize))
+ logrus.Debugf("Missing %d bytes out of %d (%.2f %%)", missingPartsSize, totalChunksSize, float32(missingPartsSize*100.0)/float32(totalChunksSize))
}
return output, nil
}
+func mustSkipFile(fileType compressedFileType, e internal.FileMetadata) bool {
+ // ignore the metadata files for the estargz format.
+ if fileType != fileTypeEstargz {
+ return false
+ }
+ switch e.Name {
+ // ignore the metadata files for the estargz format.
+ case estargz.PrefetchLandmark, estargz.NoPrefetchLandmark, estargz.TOCTarName:
+ return true
+ }
+ return false
+}
+
func (c *chunkedDiffer) mergeTocEntries(fileType compressedFileType, entries []internal.FileMetadata) ([]internal.FileMetadata, error) {
- var mergedEntries []internal.FileMetadata
- var prevEntry *internal.FileMetadata
- for _, entry := range entries {
- e := entry
+ countNextChunks := func(start int) int {
+ count := 0
+ for _, e := range entries[start:] {
+ if e.Type != TypeChunk {
+ return count
+ }
+ count++
+ }
+ return count
+ }
- // ignore the metadata files for the estargz format.
- if fileType == fileTypeEstargz && (e.Name == estargz.PrefetchLandmark || e.Name == estargz.NoPrefetchLandmark || e.Name == estargz.TOCTarName) {
+ size := 0
+ for _, entry := range entries {
+ if mustSkipFile(fileType, entry) {
continue
}
+ if entry.Type != TypeChunk {
+ size++
+ }
+ }
+ mergedEntries := make([]internal.FileMetadata, size)
+ m := 0
+ for i := 0; i < len(entries); i++ {
+ e := entries[i]
+ if mustSkipFile(fileType, e) {
+ continue
+ }
if e.Type == TypeChunk {
- if prevEntry == nil || prevEntry.Type != TypeReg {
- return nil, errors.New("chunk type without a regular file")
+ return nil, fmt.Errorf("chunk type without a regular file")
+ }
+
+ if e.Type == TypeReg {
+ nChunks := countNextChunks(i + 1)
+
+ e.Chunks = make([]*internal.FileMetadata, nChunks+1)
+ for j := 0; j <= nChunks; j++ {
+ e.Chunks[j] = &entries[i+j]
+ e.EndOffset = entries[i+j].EndOffset
}
- prevEntry.EndOffset = e.EndOffset
- continue
+ i += nChunks
}
- mergedEntries = append(mergedEntries, e)
- prevEntry = &e
+ mergedEntries[m] = e
+ m++
}
// stargz/estargz doesn't store EndOffset so let's calculate it here
lastOffset := c.tocOffset
@@ -1386,6 +1728,47 @@ func (c *chunkedDiffer) mergeTocEntries(fileType compressedFileType, entries []i
if mergedEntries[i].Offset != 0 {
lastOffset = mergedEntries[i].Offset
}
+
+ lastChunkOffset := mergedEntries[i].EndOffset
+ for j := len(mergedEntries[i].Chunks) - 1; j >= 0; j-- {
+ mergedEntries[i].Chunks[j].EndOffset = lastChunkOffset
+ mergedEntries[i].Chunks[j].Size = mergedEntries[i].Chunks[j].EndOffset - mergedEntries[i].Chunks[j].Offset
+ lastChunkOffset = mergedEntries[i].Chunks[j].Offset
+ }
}
return mergedEntries, nil
}
+
+// validateChunkChecksum checks if the file at $root/$path[offset:chunk.ChunkSize] has the
+// same digest as chunk.ChunkDigest
+func validateChunkChecksum(chunk *internal.FileMetadata, root, path string, offset int64, copyBuffer []byte) bool {
+ parentDirfd, err := unix.Open(root, unix.O_PATH, 0)
+ if err != nil {
+ return false
+ }
+ defer unix.Close(parentDirfd)
+
+ fd, err := openFileUnderRoot(path, parentDirfd, unix.O_RDONLY, 0)
+ if err != nil {
+ return false
+ }
+ defer fd.Close()
+
+ if _, err := unix.Seek(int(fd.Fd()), offset, 0); err != nil {
+ return false
+ }
+
+ r := io.LimitReader(fd, chunk.ChunkSize)
+ digester := digest.Canonical.Digester()
+
+ if _, err := io.CopyBuffer(digester.Hash(), r, copyBuffer); err != nil {
+ return false
+ }
+
+ digest, err := digest.Parse(chunk.ChunkDigest)
+ if err != nil {
+ return false
+ }
+
+ return digester.Digest() == digest
+}
diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools.go b/vendor/github.com/containers/storage/pkg/idtools/idtools.go
index 83e797599..0abe886eb 100644
--- a/vendor/github.com/containers/storage/pkg/idtools/idtools.go
+++ b/vendor/github.com/containers/storage/pkg/idtools/idtools.go
@@ -82,7 +82,7 @@ func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
if len(uidMap) == 1 && uidMap[0].Size == 1 {
uid = uidMap[0].HostID
} else {
- uid, err = toHost(0, uidMap)
+ uid, err = RawToHost(0, uidMap)
if err != nil {
return -1, -1, err
}
@@ -90,7 +90,7 @@ func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
if len(gidMap) == 1 && gidMap[0].Size == 1 {
gid = gidMap[0].HostID
} else {
- gid, err = toHost(0, gidMap)
+ gid, err = RawToHost(0, gidMap)
if err != nil {
return -1, -1, err
}
@@ -98,10 +98,14 @@ func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
return uid, gid, nil
}
-// toContainer takes an id mapping, and uses it to translate a
-// host ID to the remapped ID. If no map is provided, then the translation
-// assumes a 1-to-1 mapping and returns the passed in id
-func toContainer(hostID int, idMap []IDMap) (int, error) {
+// RawToContainer takes an id mapping, and uses it to translate a host ID to
+// the remapped ID. If no map is provided, then the translation assumes a
+// 1-to-1 mapping and returns the passed in id.
+//
+// If you wish to map a (uid,gid) combination you should use the corresponding
+// IDMappings methods, which ensure that you are mapping the correct ID against
+// the correct mapping.
+func RawToContainer(hostID int, idMap []IDMap) (int, error) {
if idMap == nil {
return hostID, nil
}
@@ -114,10 +118,14 @@ func toContainer(hostID int, idMap []IDMap) (int, error) {
return -1, fmt.Errorf("Host ID %d cannot be mapped to a container ID", hostID)
}
-// toHost takes an id mapping and a remapped ID, and translates the
-// ID to the mapped host ID. If no map is provided, then the translation
-// assumes a 1-to-1 mapping and returns the passed in id #
-func toHost(contID int, idMap []IDMap) (int, error) {
+// RawToHost takes an id mapping and a remapped ID, and translates the ID to
+// the mapped host ID. If no map is provided, then the translation assumes a
+// 1-to-1 mapping and returns the passed in id.
+//
+// If you wish to map a (uid,gid) combination you should use the corresponding
+// IDMappings methods, which ensure that you are mapping the correct ID against
+// the correct mapping.
+func RawToHost(contID int, idMap []IDMap) (int, error) {
if idMap == nil {
return contID, nil
}
@@ -187,22 +195,22 @@ func (i *IDMappings) ToHost(pair IDPair) (IDPair, error) {
var err error
var target IDPair
- target.UID, err = toHost(pair.UID, i.uids)
+ target.UID, err = RawToHost(pair.UID, i.uids)
if err != nil {
return target, err
}
- target.GID, err = toHost(pair.GID, i.gids)
+ target.GID, err = RawToHost(pair.GID, i.gids)
return target, err
}
// ToContainer returns the container UID and GID for the host uid and gid
func (i *IDMappings) ToContainer(pair IDPair) (int, int, error) {
- uid, err := toContainer(pair.UID, i.uids)
+ uid, err := RawToContainer(pair.UID, i.uids)
if err != nil {
return -1, -1, err
}
- gid, err := toContainer(pair.GID, i.gids)
+ gid, err := RawToContainer(pair.GID, i.gids)
return uid, gid, err
}
diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools_supported.go b/vendor/github.com/containers/storage/pkg/idtools/idtools_supported.go
index e444a1bcc..6e6e3b22b 100644
--- a/vendor/github.com/containers/storage/pkg/idtools/idtools_supported.go
+++ b/vendor/github.com/containers/storage/pkg/idtools/idtools_supported.go
@@ -12,10 +12,14 @@ import (
#cgo LDFLAGS: -l subid
#include <shadow/subid.h>
#include <stdlib.h>
+#include <stdio.h>
const char *Prog = "storage";
+FILE *shadow_logfd = NULL;
+
struct subid_range get_range(struct subid_range *ranges, int i)
{
- return ranges[i];
+ shadow_logfd = stderr;
+ return ranges[i];
}
#if !defined(SUBID_ABI_MAJOR) || (SUBID_ABI_MAJOR < 4)
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index bf1cd4f38..062ce6fb7 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -647,17 +647,21 @@ func GetStore(options types.StoreOptions) (Store, error) {
storesLock.Lock()
defer storesLock.Unlock()
+ // return if BOTH run and graph root are matched, otherwise our run-root can be overridden if the graph is found first
for _, s := range stores {
- if s.graphRoot == options.GraphRoot && (options.GraphDriverName == "" || s.graphDriverName == options.GraphDriverName) {
+ if (s.graphRoot == options.GraphRoot) && (s.runRoot == options.RunRoot) && (options.GraphDriverName == "" || s.graphDriverName == options.GraphDriverName) {
return s, nil
}
}
- if options.GraphRoot == "" {
- return nil, errors.Wrap(ErrIncompleteOptions, "no storage root specified")
- }
- if options.RunRoot == "" {
- return nil, errors.Wrap(ErrIncompleteOptions, "no storage runroot specified")
+ // if passed a run-root or graph-root alone, the other should be defaulted only error if we have neither.
+ switch {
+ case options.RunRoot == "" && options.GraphRoot == "":
+ return nil, errors.Wrap(ErrIncompleteOptions, "no storage runroot or graphroot specified")
+ case options.GraphRoot == "":
+ options.GraphRoot = types.Options().GraphRoot
+ case options.RunRoot == "":
+ options.RunRoot = types.Options().RunRoot
}
if err := os.MkdirAll(options.RunRoot, 0700); err != nil {
@@ -1609,7 +1613,7 @@ func (s *store) ImageBigData(id, key string) ([]byte, error) {
}
}
if foundImage {
- return nil, errors.Wrapf(os.ErrNotExist, "error locating item named %q for image with ID %q", key, id)
+ return nil, errors.Wrapf(os.ErrNotExist, "error locating item named %q for image with ID %q (consider removing the image to resolve the issue)", key, id)
}
return nil, errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id)
}
@@ -2497,23 +2501,29 @@ func (s *store) DeleteContainer(id string) error {
gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID)
wg.Add(1)
go func() {
- var err error
- for attempts := 0; attempts < 50; attempts++ {
- err = os.RemoveAll(gcpath)
- if err == nil || !system.IsEBUSY(err) {
- break
- }
- time.Sleep(time.Millisecond * 100)
+ defer wg.Done()
+ // attempt a simple rm -rf first
+ err := os.RemoveAll(gcpath)
+ if err == nil {
+ errChan <- nil
+ return
}
- errChan <- err
- wg.Done()
+ // and if it fails get to the more complicated cleanup
+ errChan <- system.EnsureRemoveAll(gcpath)
}()
rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID)
wg.Add(1)
go func() {
- errChan <- os.RemoveAll(rcpath)
- wg.Done()
+ defer wg.Done()
+ // attempt a simple rm -rf first
+ err := os.RemoveAll(rcpath)
+ if err == nil {
+ errChan <- nil
+ return
+ }
+ // and if it fails get to the more complicated cleanup
+ errChan <- system.EnsureRemoveAll(rcpath)
}()
go func() {
diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go
index 7586cd5ae..ad8377dab 100644
--- a/vendor/github.com/containers/storage/types/options.go
+++ b/vendor/github.com/containers/storage/types/options.go
@@ -17,7 +17,7 @@ import (
)
// TOML-friendly explicit tables used for conversions.
-type tomlConfig struct {
+type TomlConfig struct {
Storage struct {
Driver string `toml:"driver"`
RunRoot string `toml:"runroot"`
@@ -306,7 +306,7 @@ func ReloadConfigurationFileIfNeeded(configFile string, storeOptions *StoreOptio
// ReloadConfigurationFile parses the specified configuration file and overrides
// the configuration in storeOptions.
func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
- config := new(tomlConfig)
+ config := new(TomlConfig)
meta, err := toml.DecodeFile(configFile, &config)
if err == nil {
@@ -321,7 +321,7 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
}
}
- // Clear storeOptions of previos settings
+ // Clear storeOptions of previous settings
*storeOptions = StoreOptions{}
if config.Storage.Driver != "" {
storeOptions.GraphDriverName = config.Storage.Driver
@@ -424,3 +424,38 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
func Options() StoreOptions {
return defaultStoreOptions
}
+
+// Save overwrites the tomlConfig in storage.conf with the given conf
+func Save(conf TomlConfig, rootless bool) error {
+ configFile, err := DefaultConfigFile(rootless)
+ if err != nil {
+ return err
+ }
+ if err = os.Remove(configFile); !os.IsNotExist(err) {
+ return err
+ }
+
+ f, err := os.Open(configFile)
+ if err != nil {
+ return err
+ }
+
+ return toml.NewEncoder(f).Encode(conf)
+}
+
+// StorageConfig is used to retrieve the storage.conf toml in order to overwrite it
+func StorageConfig(rootless bool) (*TomlConfig, error) {
+ config := new(TomlConfig)
+
+ configFile, err := DefaultConfigFile(rootless)
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = toml.DecodeFile(configFile, &config)
+ if err != nil {
+ return nil, err
+ }
+
+ return config, nil
+}
diff --git a/vendor/github.com/docker/docker/opts/address_pools.go b/vendor/github.com/docker/docker/opts/address_pools.go
new file mode 100644
index 000000000..fa15c24b9
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/address_pools.go
@@ -0,0 +1,84 @@
+package opts
+
+import (
+ "encoding/csv"
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "strings"
+
+ types "github.com/docker/libnetwork/ipamutils"
+)
+
+// PoolsOpt is a Value type for parsing the default address pools definitions
+type PoolsOpt struct {
+ Values []*types.NetworkToSplit
+}
+
+// UnmarshalJSON fills values structure info from JSON input
+func (p *PoolsOpt) UnmarshalJSON(raw []byte) error {
+ return json.Unmarshal(raw, &(p.Values))
+}
+
+// Set predefined pools
+func (p *PoolsOpt) Set(value string) error {
+ csvReader := csv.NewReader(strings.NewReader(value))
+ fields, err := csvReader.Read()
+ if err != nil {
+ return err
+ }
+
+ poolsDef := types.NetworkToSplit{}
+
+ for _, field := range fields {
+ parts := strings.SplitN(field, "=", 2)
+ if len(parts) != 2 {
+ return fmt.Errorf("invalid field '%s' must be a key=value pair", field)
+ }
+
+ key := strings.ToLower(parts[0])
+ value := strings.ToLower(parts[1])
+
+ switch key {
+ case "base":
+ poolsDef.Base = value
+ case "size":
+ size, err := strconv.Atoi(value)
+ if err != nil {
+ return fmt.Errorf("invalid size value: %q (must be integer): %v", value, err)
+ }
+ poolsDef.Size = size
+ default:
+ return fmt.Errorf("unexpected key '%s' in '%s'", key, field)
+ }
+ }
+
+ p.Values = append(p.Values, &poolsDef)
+
+ return nil
+}
+
+// Type returns the type of this option
+func (p *PoolsOpt) Type() string {
+ return "pool-options"
+}
+
+// String returns a string repr of this option
+func (p *PoolsOpt) String() string {
+ var pools []string
+ for _, pool := range p.Values {
+ repr := fmt.Sprintf("%s %d", pool.Base, pool.Size)
+ pools = append(pools, repr)
+ }
+ return strings.Join(pools, ", ")
+}
+
+// Value returns the mounts
+func (p *PoolsOpt) Value() []*types.NetworkToSplit {
+ return p.Values
+}
+
+// Name returns the flag name of this option
+func (p *PoolsOpt) Name() string {
+ return "default-address-pools"
+}
diff --git a/vendor/github.com/docker/docker/opts/env.go b/vendor/github.com/docker/docker/opts/env.go
new file mode 100644
index 000000000..97e1a8c8a
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/env.go
@@ -0,0 +1,30 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "os"
+ "strings"
+
+ "github.com/pkg/errors"
+)
+
+// ValidateEnv validates an environment variable and returns it.
+// If no value is specified, it obtains its value from the current environment
+//
+// As on ParseEnvFile and related to #16585, environment variable names
+// are not validate whatsoever, it's up to application inside docker
+// to validate them or not.
+//
+// The only validation here is to check if name is empty, per #25099
+func ValidateEnv(val string) (string, error) {
+ arr := strings.SplitN(val, "=", 2)
+ if arr[0] == "" {
+ return "", errors.New("invalid environment variable: " + val)
+ }
+ if len(arr) > 1 {
+ return val, nil
+ }
+ if envVal, ok := os.LookupEnv(arr[0]); ok {
+ return arr[0] + "=" + envVal, nil
+ }
+ return val, nil
+}
diff --git a/vendor/github.com/docker/docker/opts/hosts.go b/vendor/github.com/docker/docker/opts/hosts.go
new file mode 100644
index 000000000..a3123adef
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/hosts.go
@@ -0,0 +1,183 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "fmt"
+ "net"
+ "net/url"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "github.com/docker/docker/pkg/homedir"
+)
+
+const (
+ // DefaultHTTPPort Default HTTP Port used if only the protocol is provided to -H flag e.g. dockerd -H tcp://
+ // These are the IANA registered port numbers for use with Docker
+ // see http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker
+ DefaultHTTPPort = 2375 // Default HTTP Port
+ // DefaultTLSHTTPPort Default HTTP Port used when TLS enabled
+ DefaultTLSHTTPPort = 2376 // Default TLS encrypted HTTP Port
+ // DefaultUnixSocket Path for the unix socket.
+ // Docker daemon by default always listens on the default unix socket
+ DefaultUnixSocket = "/var/run/docker.sock"
+ // DefaultTCPHost constant defines the default host string used by docker on Windows
+ DefaultTCPHost = "tcp://" + DefaultHTTPHost + ":2375"
+ // DefaultTLSHost constant defines the default host string used by docker for TLS sockets
+ DefaultTLSHost = "tcp://" + DefaultHTTPHost + ":2376"
+ // DefaultNamedPipe defines the default named pipe used by docker on Windows
+ DefaultNamedPipe = `//./pipe/docker_engine`
+ // HostGatewayName is the string value that can be passed
+ // to the IPAddr section in --add-host that is replaced by
+ // the value of HostGatewayIP daemon config value
+ HostGatewayName = "host-gateway"
+)
+
+// ValidateHost validates that the specified string is a valid host and returns it.
+func ValidateHost(val string) (string, error) {
+ host := strings.TrimSpace(val)
+ // The empty string means default and is not handled by parseDaemonHost
+ if host != "" {
+ _, err := parseDaemonHost(host)
+ if err != nil {
+ return val, err
+ }
+ }
+ // Note: unlike most flag validators, we don't return the mutated value here
+ // we need to know what the user entered later (using ParseHost) to adjust for TLS
+ return val, nil
+}
+
+// ParseHost and set defaults for a Daemon host string.
+// defaultToTLS is preferred over defaultToUnixXDG.
+func ParseHost(defaultToTLS, defaultToUnixXDG bool, val string) (string, error) {
+ host := strings.TrimSpace(val)
+ if host == "" {
+ if defaultToTLS {
+ host = DefaultTLSHost
+ } else if defaultToUnixXDG {
+ runtimeDir, err := homedir.GetRuntimeDir()
+ if err != nil {
+ return "", err
+ }
+ socket := filepath.Join(runtimeDir, "docker.sock")
+ host = "unix://" + socket
+ } else {
+ host = DefaultHost
+ }
+ } else {
+ var err error
+ host, err = parseDaemonHost(host)
+ if err != nil {
+ return val, err
+ }
+ }
+ return host, nil
+}
+
+// parseDaemonHost parses the specified address and returns an address that will be used as the host.
+// Depending of the address specified, this may return one of the global Default* strings defined in hosts.go.
+func parseDaemonHost(addr string) (string, error) {
+ addrParts := strings.SplitN(addr, "://", 2)
+ if len(addrParts) == 1 && addrParts[0] != "" {
+ addrParts = []string{"tcp", addrParts[0]}
+ }
+
+ switch addrParts[0] {
+ case "tcp":
+ return ParseTCPAddr(addrParts[1], DefaultTCPHost)
+ case "unix":
+ return parseSimpleProtoAddr("unix", addrParts[1], DefaultUnixSocket)
+ case "npipe":
+ return parseSimpleProtoAddr("npipe", addrParts[1], DefaultNamedPipe)
+ case "fd":
+ return addr, nil
+ default:
+ return "", fmt.Errorf("Invalid bind address format: %s", addr)
+ }
+}
+
+// parseSimpleProtoAddr parses and validates that the specified address is a valid
+// socket address for simple protocols like unix and npipe. It returns a formatted
+// socket address, either using the address parsed from addr, or the contents of
+// defaultAddr if addr is a blank string.
+func parseSimpleProtoAddr(proto, addr, defaultAddr string) (string, error) {
+ addr = strings.TrimPrefix(addr, proto+"://")
+ if strings.Contains(addr, "://") {
+ return "", fmt.Errorf("Invalid proto, expected %s: %s", proto, addr)
+ }
+ if addr == "" {
+ addr = defaultAddr
+ }
+ return fmt.Sprintf("%s://%s", proto, addr), nil
+}
+
+// ParseTCPAddr parses and validates that the specified address is a valid TCP
+// address. It returns a formatted TCP address, either using the address parsed
+// from tryAddr, or the contents of defaultAddr if tryAddr is a blank string.
+// tryAddr is expected to have already been Trim()'d
+// defaultAddr must be in the full `tcp://host:port` form
+func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) {
+ if tryAddr == "" || tryAddr == "tcp://" {
+ return defaultAddr, nil
+ }
+ addr := strings.TrimPrefix(tryAddr, "tcp://")
+ if strings.Contains(addr, "://") || addr == "" {
+ return "", fmt.Errorf("Invalid proto, expected tcp: %s", tryAddr)
+ }
+
+ defaultAddr = strings.TrimPrefix(defaultAddr, "tcp://")
+ defaultHost, defaultPort, err := net.SplitHostPort(defaultAddr)
+ if err != nil {
+ return "", err
+ }
+ // url.Parse fails for trailing colon on IPv6 brackets on Go 1.5, but
+ // not 1.4. See https://github.com/golang/go/issues/12200 and
+ // https://github.com/golang/go/issues/6530.
+ if strings.HasSuffix(addr, "]:") {
+ addr += defaultPort
+ }
+
+ u, err := url.Parse("tcp://" + addr)
+ if err != nil {
+ return "", err
+ }
+ host, port, err := net.SplitHostPort(u.Host)
+ if err != nil {
+ // try port addition once
+ host, port, err = net.SplitHostPort(net.JoinHostPort(u.Host, defaultPort))
+ }
+ if err != nil {
+ return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
+ }
+
+ if host == "" {
+ host = defaultHost
+ }
+ if port == "" {
+ port = defaultPort
+ }
+ p, err := strconv.Atoi(port)
+ if err != nil && p == 0 {
+ return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
+ }
+
+ return fmt.Sprintf("tcp://%s%s", net.JoinHostPort(host, port), u.Path), nil
+}
+
+// ValidateExtraHost validates that the specified string is a valid extrahost and returns it.
+// ExtraHost is in the form of name:ip where the ip has to be a valid ip (IPv4 or IPv6).
+func ValidateExtraHost(val string) (string, error) {
+ // allow for IPv6 addresses in extra hosts by only splitting on first ":"
+ arr := strings.SplitN(val, ":", 2)
+ if len(arr) != 2 || len(arr[0]) == 0 {
+ return "", fmt.Errorf("bad format for add-host: %q", val)
+ }
+ // Skip IPaddr validation for special "host-gateway" string
+ if arr[1] != HostGatewayName {
+ if _, err := ValidateIPAddress(arr[1]); err != nil {
+ return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1])
+ }
+ }
+ return val, nil
+}
diff --git a/vendor/github.com/docker/docker/opts/hosts_unix.go b/vendor/github.com/docker/docker/opts/hosts_unix.go
new file mode 100644
index 000000000..29864194a
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/hosts_unix.go
@@ -0,0 +1,11 @@
+// +build !windows
+
+package opts // import "github.com/docker/docker/opts"
+
+const (
+ // DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
+ DefaultHTTPHost = "localhost"
+
+ // DefaultHost constant defines the default host string used by docker on other hosts than Windows
+ DefaultHost = "unix://" + DefaultUnixSocket
+)
diff --git a/vendor/github.com/docker/docker/opts/hosts_windows.go b/vendor/github.com/docker/docker/opts/hosts_windows.go
new file mode 100644
index 000000000..576236ba4
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/hosts_windows.go
@@ -0,0 +1,60 @@
+package opts // import "github.com/docker/docker/opts"
+
+const (
+ // TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5.
+ //
+ // On Windows, this mitigates a problem with the default options of running
+ // a docker client against a local docker daemon on TP5.
+ //
+ // What was found that if the default host is "localhost", even if the client
+ // (and daemon as this is local) is not physically on a network, and the DNS
+ // cache is flushed (ipconfig /flushdns), then the client will pause for
+ // exactly one second when connecting to the daemon for calls. For example
+ // using docker run windowsservercore cmd, the CLI will send a create followed
+ // by an attach. You see the delay between the attach finishing and the attach
+ // being seen by the daemon.
+ //
+ // Here's some daemon debug logs with additional debug spew put in. The
+ // AfterWriteJSON log is the very last thing the daemon does as part of the
+ // create call. The POST /attach is the second CLI call. Notice the second
+ // time gap.
+ //
+ // time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs"
+ // time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig"
+ // time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...."
+ // time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking....
+ // time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...."
+ // time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...."
+ // time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func"
+ // time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create"
+ // time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2"
+ // time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate"
+ // time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON"
+ // ... 1 second gap here....
+ // time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach"
+ // time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1"
+ //
+ // We suspect this is either a bug introduced in GOLang 1.5.1, or that a change
+ // in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory,
+ // the Windows networking stack is supposed to resolve "localhost" internally,
+ // without hitting DNS, or even reading the hosts file (which is why localhost
+ // is commented out in the hosts file on Windows).
+ //
+ // We have validated that working around this using the actual IPv4 localhost
+ // address does not cause the delay.
+ //
+ // This does not occur with the docker client built with 1.4.3 on the same
+ // Windows build, regardless of whether the daemon is built using 1.5.1
+ // or 1.4.3. It does not occur on Linux. We also verified we see the same thing
+ // on a cross-compiled Windows binary (from Linux).
+ //
+ // Final note: This is a mitigation, not a 'real' fix. It is still susceptible
+ // to the delay if a user were to do 'docker run -H=tcp://localhost:2375...'
+ // explicitly.
+
+ // DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
+ DefaultHTTPHost = "127.0.0.1"
+
+ // DefaultHost constant defines the default host string used by docker on Windows
+ DefaultHost = "npipe://" + DefaultNamedPipe
+)
diff --git a/vendor/github.com/docker/docker/opts/ip.go b/vendor/github.com/docker/docker/opts/ip.go
new file mode 100644
index 000000000..cfbff3a9f
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/ip.go
@@ -0,0 +1,47 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "fmt"
+ "net"
+)
+
+// IPOpt holds an IP. It is used to store values from CLI flags.
+type IPOpt struct {
+ *net.IP
+}
+
+// NewIPOpt creates a new IPOpt from a reference net.IP and a
+// string representation of an IP. If the string is not a valid
+// IP it will fallback to the specified reference.
+func NewIPOpt(ref *net.IP, defaultVal string) *IPOpt {
+ o := &IPOpt{
+ IP: ref,
+ }
+ o.Set(defaultVal)
+ return o
+}
+
+// Set sets an IPv4 or IPv6 address from a given string. If the given
+// string is not parsable as an IP address it returns an error.
+func (o *IPOpt) Set(val string) error {
+ ip := net.ParseIP(val)
+ if ip == nil {
+ return fmt.Errorf("%s is not an ip address", val)
+ }
+ *o.IP = ip
+ return nil
+}
+
+// String returns the IP address stored in the IPOpt. If stored IP is a
+// nil pointer, it returns an empty string.
+func (o *IPOpt) String() string {
+ if *o.IP == nil {
+ return ""
+ }
+ return o.IP.String()
+}
+
+// Type returns the type of the option
+func (o *IPOpt) Type() string {
+ return "ip"
+}
diff --git a/vendor/github.com/docker/docker/opts/opts.go b/vendor/github.com/docker/docker/opts/opts.go
new file mode 100644
index 000000000..60a093f28
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/opts.go
@@ -0,0 +1,348 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "fmt"
+ "net"
+ "path"
+ "regexp"
+ "strings"
+
+ units "github.com/docker/go-units"
+)
+
+var (
+ alphaRegexp = regexp.MustCompile(`[a-zA-Z]`)
+ domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
+)
+
+// ListOpts holds a list of values and a validation function.
+type ListOpts struct {
+ values *[]string
+ validator ValidatorFctType
+}
+
+// NewListOpts creates a new ListOpts with the specified validator.
+func NewListOpts(validator ValidatorFctType) ListOpts {
+ var values []string
+ return *NewListOptsRef(&values, validator)
+}
+
+// NewListOptsRef creates a new ListOpts with the specified values and validator.
+func NewListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts {
+ return &ListOpts{
+ values: values,
+ validator: validator,
+ }
+}
+
+func (opts *ListOpts) String() string {
+ if len(*opts.values) == 0 {
+ return ""
+ }
+ return fmt.Sprintf("%v", *opts.values)
+}
+
+// Set validates if needed the input value and adds it to the
+// internal slice.
+func (opts *ListOpts) Set(value string) error {
+ if opts.validator != nil {
+ v, err := opts.validator(value)
+ if err != nil {
+ return err
+ }
+ value = v
+ }
+ *opts.values = append(*opts.values, value)
+ return nil
+}
+
+// Delete removes the specified element from the slice.
+func (opts *ListOpts) Delete(key string) {
+ for i, k := range *opts.values {
+ if k == key {
+ *opts.values = append((*opts.values)[:i], (*opts.values)[i+1:]...)
+ return
+ }
+ }
+}
+
+// GetMap returns the content of values in a map in order to avoid
+// duplicates.
+func (opts *ListOpts) GetMap() map[string]struct{} {
+ ret := make(map[string]struct{})
+ for _, k := range *opts.values {
+ ret[k] = struct{}{}
+ }
+ return ret
+}
+
+// GetAll returns the values of slice.
+func (opts *ListOpts) GetAll() []string {
+ return *opts.values
+}
+
+// GetAllOrEmpty returns the values of the slice
+// or an empty slice when there are no values.
+func (opts *ListOpts) GetAllOrEmpty() []string {
+ v := *opts.values
+ if v == nil {
+ return make([]string, 0)
+ }
+ return v
+}
+
+// Get checks the existence of the specified key.
+func (opts *ListOpts) Get(key string) bool {
+ for _, k := range *opts.values {
+ if k == key {
+ return true
+ }
+ }
+ return false
+}
+
+// Len returns the amount of element in the slice.
+func (opts *ListOpts) Len() int {
+ return len(*opts.values)
+}
+
+// Type returns a string name for this Option type
+func (opts *ListOpts) Type() string {
+ return "list"
+}
+
+// WithValidator returns the ListOpts with validator set.
+func (opts *ListOpts) WithValidator(validator ValidatorFctType) *ListOpts {
+ opts.validator = validator
+ return opts
+}
+
+// NamedOption is an interface that list and map options
+// with names implement.
+type NamedOption interface {
+ Name() string
+}
+
+// NamedListOpts is a ListOpts with a configuration name.
+// This struct is useful to keep reference to the assigned
+// field name in the internal configuration struct.
+type NamedListOpts struct {
+ name string
+ ListOpts
+}
+
+var _ NamedOption = &NamedListOpts{}
+
+// NewNamedListOptsRef creates a reference to a new NamedListOpts struct.
+func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts {
+ return &NamedListOpts{
+ name: name,
+ ListOpts: *NewListOptsRef(values, validator),
+ }
+}
+
+// Name returns the name of the NamedListOpts in the configuration.
+func (o *NamedListOpts) Name() string {
+ return o.name
+}
+
+// MapOpts holds a map of values and a validation function.
+type MapOpts struct {
+ values map[string]string
+ validator ValidatorFctType
+}
+
+// Set validates if needed the input value and add it to the
+// internal map, by splitting on '='.
+func (opts *MapOpts) Set(value string) error {
+ if opts.validator != nil {
+ v, err := opts.validator(value)
+ if err != nil {
+ return err
+ }
+ value = v
+ }
+ vals := strings.SplitN(value, "=", 2)
+ if len(vals) == 1 {
+ (opts.values)[vals[0]] = ""
+ } else {
+ (opts.values)[vals[0]] = vals[1]
+ }
+ return nil
+}
+
+// GetAll returns the values of MapOpts as a map.
+func (opts *MapOpts) GetAll() map[string]string {
+ return opts.values
+}
+
+func (opts *MapOpts) String() string {
+ return fmt.Sprintf("%v", opts.values)
+}
+
+// Type returns a string name for this Option type
+func (opts *MapOpts) Type() string {
+ return "map"
+}
+
+// NewMapOpts creates a new MapOpts with the specified map of values and a validator.
+func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts {
+ if values == nil {
+ values = make(map[string]string)
+ }
+ return &MapOpts{
+ values: values,
+ validator: validator,
+ }
+}
+
+// NamedMapOpts is a MapOpts struct with a configuration name.
+// This struct is useful to keep reference to the assigned
+// field name in the internal configuration struct.
+type NamedMapOpts struct {
+ name string
+ MapOpts
+}
+
+var _ NamedOption = &NamedMapOpts{}
+
+// NewNamedMapOpts creates a reference to a new NamedMapOpts struct.
+func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts {
+ return &NamedMapOpts{
+ name: name,
+ MapOpts: *NewMapOpts(values, validator),
+ }
+}
+
+// Name returns the name of the NamedMapOpts in the configuration.
+func (o *NamedMapOpts) Name() string {
+ return o.name
+}
+
+// ValidatorFctType defines a validator function that returns a validated string and/or an error.
+type ValidatorFctType func(val string) (string, error)
+
+// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
+type ValidatorFctListType func(val string) ([]string, error)
+
+// ValidateIPAddress validates an Ip address.
+func ValidateIPAddress(val string) (string, error) {
+ var ip = net.ParseIP(strings.TrimSpace(val))
+ if ip != nil {
+ return ip.String(), nil
+ }
+ return "", fmt.Errorf("%s is not an ip address", val)
+}
+
+// ValidateDNSSearch validates domain for resolvconf search configuration.
+// A zero length domain is represented by a dot (.).
+func ValidateDNSSearch(val string) (string, error) {
+ if val = strings.Trim(val, " "); val == "." {
+ return val, nil
+ }
+ return validateDomain(val)
+}
+
+func validateDomain(val string) (string, error) {
+ if alphaRegexp.FindString(val) == "" {
+ return "", fmt.Errorf("%s is not a valid domain", val)
+ }
+ ns := domainRegexp.FindSubmatch([]byte(val))
+ if len(ns) > 0 && len(ns[1]) < 255 {
+ return string(ns[1]), nil
+ }
+ return "", fmt.Errorf("%s is not a valid domain", val)
+}
+
+// ValidateLabel validates that the specified string is a valid label,
+// it does not use the reserved namespaces com.docker.*, io.docker.*, org.dockerproject.*
+// and returns it.
+// Labels are in the form on key=value.
+func ValidateLabel(val string) (string, error) {
+ if strings.Count(val, "=") < 1 {
+ return "", fmt.Errorf("bad attribute format: %s", val)
+ }
+
+ lowered := strings.ToLower(val)
+ if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") ||
+ strings.HasPrefix(lowered, "org.dockerproject.") {
+ return "", fmt.Errorf(
+ "label %s is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use",
+ val)
+ }
+
+ return val, nil
+}
+
+// ValidateSingleGenericResource validates that a single entry in the
+// generic resource list is valid.
+// i.e 'GPU=UID1' is valid however 'GPU:UID1' or 'UID1' isn't
+func ValidateSingleGenericResource(val string) (string, error) {
+ if strings.Count(val, "=") < 1 {
+ return "", fmt.Errorf("invalid node-generic-resource format `%s` expected `name=value`", val)
+ }
+ return val, nil
+}
+
+// ParseLink parses and validates the specified string as a link format (name:alias)
+func ParseLink(val string) (string, string, error) {
+ if val == "" {
+ return "", "", fmt.Errorf("empty string specified for links")
+ }
+ arr := strings.Split(val, ":")
+ if len(arr) > 2 {
+ return "", "", fmt.Errorf("bad format for links: %s", val)
+ }
+ if len(arr) == 1 {
+ return val, val, nil
+ }
+ // This is kept because we can actually get a HostConfig with links
+ // from an already created container and the format is not `foo:bar`
+ // but `/foo:/c1/bar`
+ if strings.HasPrefix(arr[0], "/") {
+ _, alias := path.Split(arr[1])
+ return arr[0][1:], alias, nil
+ }
+ return arr[0], arr[1], nil
+}
+
+// MemBytes is a type for human readable memory bytes (like 128M, 2g, etc)
+type MemBytes int64
+
+// String returns the string format of the human readable memory bytes
+func (m *MemBytes) String() string {
+ // NOTE: In spf13/pflag/flag.go, "0" is considered as "zero value" while "0 B" is not.
+ // We return "0" in case value is 0 here so that the default value is hidden.
+ // (Sometimes "default 0 B" is actually misleading)
+ if m.Value() != 0 {
+ return units.BytesSize(float64(m.Value()))
+ }
+ return "0"
+}
+
+// Set sets the value of the MemBytes by passing a string
+func (m *MemBytes) Set(value string) error {
+ val, err := units.RAMInBytes(value)
+ *m = MemBytes(val)
+ return err
+}
+
+// Type returns the type
+func (m *MemBytes) Type() string {
+ return "bytes"
+}
+
+// Value returns the value in int64
+func (m *MemBytes) Value() int64 {
+ return int64(*m)
+}
+
+// UnmarshalJSON is the customized unmarshaler for MemBytes
+func (m *MemBytes) UnmarshalJSON(s []byte) error {
+ if len(s) <= 2 || s[0] != '"' || s[len(s)-1] != '"' {
+ return fmt.Errorf("invalid size: %q", s)
+ }
+ val, err := units.RAMInBytes(string(s[1 : len(s)-1]))
+ *m = MemBytes(val)
+ return err
+}
diff --git a/vendor/github.com/docker/docker/opts/quotedstring.go b/vendor/github.com/docker/docker/opts/quotedstring.go
new file mode 100644
index 000000000..6c889070e
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/quotedstring.go
@@ -0,0 +1,37 @@
+package opts // import "github.com/docker/docker/opts"
+
+// QuotedString is a string that may have extra quotes around the value. The
+// quotes are stripped from the value.
+type QuotedString struct {
+ value *string
+}
+
+// Set sets a new value
+func (s *QuotedString) Set(val string) error {
+ *s.value = trimQuotes(val)
+ return nil
+}
+
+// Type returns the type of the value
+func (s *QuotedString) Type() string {
+ return "string"
+}
+
+func (s *QuotedString) String() string {
+ return *s.value
+}
+
+func trimQuotes(value string) string {
+ lastIndex := len(value) - 1
+ for _, char := range []byte{'\'', '"'} {
+ if value[0] == char && value[lastIndex] == char {
+ return value[1:lastIndex]
+ }
+ }
+ return value
+}
+
+// NewQuotedString returns a new quoted string option
+func NewQuotedString(value *string) *QuotedString {
+ return &QuotedString{value: value}
+}
diff --git a/vendor/github.com/docker/docker/opts/runtime.go b/vendor/github.com/docker/docker/opts/runtime.go
new file mode 100644
index 000000000..4b9babf0a
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/runtime.go
@@ -0,0 +1,79 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/docker/docker/api/types"
+)
+
+// RuntimeOpt defines a map of Runtimes
+type RuntimeOpt struct {
+ name string
+ stockRuntimeName string
+ values *map[string]types.Runtime
+}
+
+// NewNamedRuntimeOpt creates a new RuntimeOpt
+func NewNamedRuntimeOpt(name string, ref *map[string]types.Runtime, stockRuntime string) *RuntimeOpt {
+ if ref == nil {
+ ref = &map[string]types.Runtime{}
+ }
+ return &RuntimeOpt{name: name, values: ref, stockRuntimeName: stockRuntime}
+}
+
+// Name returns the name of the NamedListOpts in the configuration.
+func (o *RuntimeOpt) Name() string {
+ return o.name
+}
+
+// Set validates and updates the list of Runtimes
+func (o *RuntimeOpt) Set(val string) error {
+ parts := strings.SplitN(val, "=", 2)
+ if len(parts) != 2 {
+ return fmt.Errorf("invalid runtime argument: %s", val)
+ }
+
+ parts[0] = strings.TrimSpace(parts[0])
+ parts[1] = strings.TrimSpace(parts[1])
+ if parts[0] == "" || parts[1] == "" {
+ return fmt.Errorf("invalid runtime argument: %s", val)
+ }
+
+ parts[0] = strings.ToLower(parts[0])
+ if parts[0] == o.stockRuntimeName {
+ return fmt.Errorf("runtime name '%s' is reserved", o.stockRuntimeName)
+ }
+
+ if _, ok := (*o.values)[parts[0]]; ok {
+ return fmt.Errorf("runtime '%s' was already defined", parts[0])
+ }
+
+ (*o.values)[parts[0]] = types.Runtime{Path: parts[1]}
+
+ return nil
+}
+
+// String returns Runtime values as a string.
+func (o *RuntimeOpt) String() string {
+ var out []string
+ for k := range *o.values {
+ out = append(out, k)
+ }
+
+ return fmt.Sprintf("%v", out)
+}
+
+// GetMap returns a map of Runtimes (name: path)
+func (o *RuntimeOpt) GetMap() map[string]types.Runtime {
+ if o.values != nil {
+ return *o.values
+ }
+
+ return map[string]types.Runtime{}
+}
+
+// Type returns the type of the option
+func (o *RuntimeOpt) Type() string {
+ return "runtime"
+}
diff --git a/vendor/github.com/docker/docker/opts/ulimit.go b/vendor/github.com/docker/docker/opts/ulimit.go
new file mode 100644
index 000000000..61cc58d4d
--- /dev/null
+++ b/vendor/github.com/docker/docker/opts/ulimit.go
@@ -0,0 +1,81 @@
+package opts // import "github.com/docker/docker/opts"
+
+import (
+ "fmt"
+
+ units "github.com/docker/go-units"
+)
+
+// UlimitOpt defines a map of Ulimits
+type UlimitOpt struct {
+ values *map[string]*units.Ulimit
+}
+
+// NewUlimitOpt creates a new UlimitOpt
+func NewUlimitOpt(ref *map[string]*units.Ulimit) *UlimitOpt {
+ if ref == nil {
+ ref = &map[string]*units.Ulimit{}
+ }
+ return &UlimitOpt{ref}
+}
+
+// Set validates a Ulimit and sets its name as a key in UlimitOpt
+func (o *UlimitOpt) Set(val string) error {
+ l, err := units.ParseUlimit(val)
+ if err != nil {
+ return err
+ }
+
+ (*o.values)[l.Name] = l
+
+ return nil
+}
+
+// String returns Ulimit values as a string.
+func (o *UlimitOpt) String() string {
+ var out []string
+ for _, v := range *o.values {
+ out = append(out, v.String())
+ }
+
+ return fmt.Sprintf("%v", out)
+}
+
+// GetList returns a slice of pointers to Ulimits.
+func (o *UlimitOpt) GetList() []*units.Ulimit {
+ var ulimits []*units.Ulimit
+ for _, v := range *o.values {
+ ulimits = append(ulimits, v)
+ }
+
+ return ulimits
+}
+
+// Type returns the option type
+func (o *UlimitOpt) Type() string {
+ return "ulimit"
+}
+
+// NamedUlimitOpt defines a named map of Ulimits
+type NamedUlimitOpt struct {
+ name string
+ UlimitOpt
+}
+
+var _ NamedOption = &NamedUlimitOpt{}
+
+// NewNamedUlimitOpt creates a new NamedUlimitOpt
+func NewNamedUlimitOpt(name string, ref *map[string]*units.Ulimit) *NamedUlimitOpt {
+ if ref == nil {
+ ref = &map[string]*units.Ulimit{}
+ }
+ return &NamedUlimitOpt{
+ name: name,
+ UlimitOpt: *NewUlimitOpt(ref),
+ }
+}
+
+// Name returns the option name
+func (o *NamedUlimitOpt) Name() string {
+ return o.name
+}
diff --git a/vendor/github.com/docker/go-connections/nat/nat.go b/vendor/github.com/docker/go-connections/nat/nat.go
index bb7e4e336..296c96a63 100644
--- a/vendor/github.com/docker/go-connections/nat/nat.go
+++ b/vendor/github.com/docker/go-connections/nat/nat.go
@@ -8,11 +8,6 @@ import (
"strings"
)
-const (
- // portSpecTemplate is the expected format for port specifications
- portSpecTemplate = "ip:hostPort:containerPort"
-)
-
// PortBinding represents a binding between a Host IP address and a Host Port
type PortBinding struct {
// HostIP is the host IP Address
@@ -158,30 +153,33 @@ type PortMapping struct {
func splitParts(rawport string) (string, string, string) {
parts := strings.Split(rawport, ":")
n := len(parts)
- containerport := parts[n-1]
+ containerPort := parts[n-1]
switch n {
case 1:
- return "", "", containerport
+ return "", "", containerPort
case 2:
- return "", parts[0], containerport
+ return "", parts[0], containerPort
case 3:
- return parts[0], parts[1], containerport
+ return parts[0], parts[1], containerPort
default:
- return strings.Join(parts[:n-2], ":"), parts[n-2], containerport
+ return strings.Join(parts[:n-2], ":"), parts[n-2], containerPort
}
}
// ParsePortSpec parses a port specification string into a slice of PortMappings
func ParsePortSpec(rawPort string) ([]PortMapping, error) {
var proto string
- rawIP, hostPort, containerPort := splitParts(rawPort)
+ ip, hostPort, containerPort := splitParts(rawPort)
proto, containerPort = SplitProtoPort(containerPort)
- // Strip [] from IPV6 addresses
- ip, _, err := net.SplitHostPort(rawIP + ":")
- if err != nil {
- return nil, fmt.Errorf("Invalid ip address %v: %s", rawIP, err)
+ if ip != "" && ip[0] == '[' {
+ // Strip [] from IPV6 addresses
+ rawIP, _, err := net.SplitHostPort(ip + ":")
+ if err != nil {
+ return nil, fmt.Errorf("Invalid ip address %v: %s", ip, err)
+ }
+ ip = rawIP
}
if ip != "" && net.ParseIP(ip) == nil {
return nil, fmt.Errorf("Invalid ip address: %s", ip)
diff --git a/vendor/github.com/docker/go-connections/nat/sort.go b/vendor/github.com/docker/go-connections/nat/sort.go
index ce950171e..b6eed145e 100644
--- a/vendor/github.com/docker/go-connections/nat/sort.go
+++ b/vendor/github.com/docker/go-connections/nat/sort.go
@@ -43,7 +43,7 @@ type portMapSorter []portMapEntry
func (s portMapSorter) Len() int { return len(s) }
func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-// sort the port so that the order is:
+// Less sorts the port so that the order is:
// 1. port with larger specified bindings
// 2. larger port
// 3. port with tcp protocol
@@ -58,7 +58,7 @@ func (s portMapSorter) Less(i, j int) bool {
func SortPortMap(ports []Port, bindings PortMap) {
s := portMapSorter{}
for _, p := range ports {
- if binding, ok := bindings[p]; ok {
+ if binding, ok := bindings[p]; ok && len(binding) > 0 {
for _, b := range binding {
s = append(s, portMapEntry{port: p, binding: b})
}
diff --git a/vendor/github.com/docker/go-connections/sockets/proxy.go b/vendor/github.com/docker/go-connections/sockets/proxy.go
index 98e9a1dc6..c897cb02a 100644
--- a/vendor/github.com/docker/go-connections/sockets/proxy.go
+++ b/vendor/github.com/docker/go-connections/sockets/proxy.go
@@ -2,11 +2,8 @@ package sockets
import (
"net"
- "net/url"
"os"
"strings"
-
- "golang.org/x/net/proxy"
)
// GetProxyEnv allows access to the uppercase and the lowercase forms of
@@ -20,32 +17,12 @@ func GetProxyEnv(key string) string {
return proxyValue
}
-// DialerFromEnvironment takes in a "direct" *net.Dialer and returns a
-// proxy.Dialer which will route the connections through the proxy using the
-// given dialer.
-func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) {
- allProxy := GetProxyEnv("all_proxy")
- if len(allProxy) == 0 {
- return direct, nil
- }
-
- proxyURL, err := url.Parse(allProxy)
- if err != nil {
- return direct, err
- }
-
- proxyFromURL, err := proxy.FromURL(proxyURL, direct)
- if err != nil {
- return direct, err
- }
-
- noProxy := GetProxyEnv("no_proxy")
- if len(noProxy) == 0 {
- return proxyFromURL, nil
- }
-
- perHost := proxy.NewPerHost(proxyFromURL, direct)
- perHost.AddFromString(noProxy)
-
- return perHost, nil
+// DialerFromEnvironment was previously used to configure a net.Dialer to route
+// connections through a SOCKS proxy.
+// DEPRECATED: SOCKS proxies are now supported by configuring only
+// http.Transport.Proxy, and no longer require changing http.Transport.Dial.
+// Therefore, only sockets.ConfigureTransport() needs to be called, and any
+// sockets.DialerFromEnvironment() calls can be dropped.
+func DialerFromEnvironment(direct *net.Dialer) (*net.Dialer, error) {
+ return direct, nil
}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets.go b/vendor/github.com/docker/go-connections/sockets/sockets.go
index a1d7beb4d..2e9e9006f 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets.go
@@ -3,14 +3,9 @@ package sockets
import (
"errors"
- "net"
"net/http"
- "time"
)
-// Why 32? See https://github.com/docker/docker/pull/8035.
-const defaultTimeout = 32 * time.Second
-
// ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system.
var ErrProtocolNotAvailable = errors.New("protocol not available")
@@ -26,13 +21,6 @@ func ConfigureTransport(tr *http.Transport, proto, addr string) error {
return configureNpipeTransport(tr, proto, addr)
default:
tr.Proxy = http.ProxyFromEnvironment
- dialer, err := DialerFromEnvironment(&net.Dialer{
- Timeout: defaultTimeout,
- })
- if err != nil {
- return err
- }
- tr.Dial = dialer.Dial
}
return nil
}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
index 386cf0dbb..10d763426 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_unix.go
@@ -3,6 +3,7 @@
package sockets
import (
+ "context"
"fmt"
"net"
"net/http"
@@ -10,7 +11,10 @@ import (
"time"
)
-const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
+const (
+ defaultTimeout = 10 * time.Second
+ maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
+)
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
if len(addr) > maxUnixSocketPathSize {
@@ -18,8 +22,11 @@ func configureUnixTransport(tr *http.Transport, proto, addr string) error {
}
// No need for compression in local communications.
tr.DisableCompression = true
- tr.Dial = func(_, _ string) (net.Conn, error) {
- return net.DialTimeout(proto, addr, defaultTimeout)
+ dialer := &net.Dialer{
+ Timeout: defaultTimeout,
+ }
+ tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
+ return dialer.DialContext(ctx, proto, addr)
}
return nil
}
diff --git a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
index 5c21644e1..7acafc5a2 100644
--- a/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
+++ b/vendor/github.com/docker/go-connections/sockets/sockets_windows.go
@@ -1,6 +1,7 @@
package sockets
import (
+ "context"
"net"
"net/http"
"time"
@@ -15,8 +16,8 @@ func configureUnixTransport(tr *http.Transport, proto, addr string) error {
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
// No need for compression in local communications.
tr.DisableCompression = true
- tr.Dial = func(_, _ string) (net.Conn, error) {
- return DialPipe(addr, defaultTimeout)
+ tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
+ return winio.DialPipeContext(ctx, addr)
}
return nil
}
diff --git a/vendor/github.com/docker/go-connections/sockets/unix_socket.go b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
index a8b5dbb6f..e7591e6ed 100644
--- a/vendor/github.com/docker/go-connections/sockets/unix_socket.go
+++ b/vendor/github.com/docker/go-connections/sockets/unix_socket.go
@@ -1,5 +1,51 @@
// +build !windows
+/*
+Package sockets is a simple unix domain socket wrapper.
+
+Usage
+
+For example:
+
+ import(
+ "fmt"
+ "net"
+ "os"
+ "github.com/docker/go-connections/sockets"
+ )
+
+ func main() {
+ l, err := sockets.NewUnixSocketWithOpts("/path/to/sockets",
+ sockets.WithChown(0,0),sockets.WithChmod(0660))
+ if err != nil {
+ panic(err)
+ }
+ echoStr := "hello"
+
+ go func() {
+ for {
+ conn, err := l.Accept()
+ if err != nil {
+ return
+ }
+ conn.Write([]byte(echoStr))
+ conn.Close()
+ }
+ }()
+
+ conn, err := net.Dial("unix", path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ buf := make([]byte, 5)
+ if _, err := conn.Read(buf); err != nil {
+ panic(err)
+ } else if string(buf) != echoStr {
+ panic(fmt.Errorf("Msg may lost"))
+ }
+ }
+*/
package sockets
import (
@@ -8,25 +54,73 @@ import (
"syscall"
)
-// NewUnixSocket creates a unix socket with the specified path and group.
-func NewUnixSocket(path string, gid int) (net.Listener, error) {
+// SockOption sets up socket file's creating option
+type SockOption func(string) error
+
+// WithChown modifies the socket file's uid and gid
+func WithChown(uid, gid int) SockOption {
+ return func(path string) error {
+ if err := os.Chown(path, uid, gid); err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+// WithChmod modifies socket file's access mode.
+func WithChmod(mask os.FileMode) SockOption {
+ return func(path string) error {
+ if err := os.Chmod(path, mask); err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+// NewUnixSocketWithOpts creates a unix socket with the specified options.
+// By default, socket permissions are 0000 (i.e.: no access for anyone); pass
+// WithChmod() and WithChown() to set the desired ownership and permissions.
+//
+// This function temporarily changes the system's "umask" to 0777 to work around
+// a race condition between creating the socket and setting its permissions. While
+// this should only be for a short duration, it may affect other processes that
+// create files/directories during that period.
+func NewUnixSocketWithOpts(path string, opts ...SockOption) (net.Listener, error) {
if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
return nil, err
}
- mask := syscall.Umask(0777)
- defer syscall.Umask(mask)
+ // net.Listen does not allow for permissions to be set. As a result, when
+ // specifying custom permissions ("WithChmod()"), there is a short time
+ // between creating the socket and applying the permissions, during which
+ // the socket permissions are Less restrictive than desired.
+ //
+ // To work around this limitation of net.Listen(), we temporarily set the
+ // umask to 0777, which forces the socket to be created with 000 permissions
+ // (i.e.: no access for anyone). After that, WithChmod() must be used to set
+ // the desired permissions.
+ //
+ // We don't use "defer" here, to reset the umask to its original value as soon
+ // as possible. Ideally we'd be able to detect if WithChmod() was passed as
+ // an option, and skip changing umask if default permissions are used.
+ origUmask := syscall.Umask(0777)
l, err := net.Listen("unix", path)
+ syscall.Umask(origUmask)
if err != nil {
return nil, err
}
- if err := os.Chown(path, 0, gid); err != nil {
- l.Close()
- return nil, err
- }
- if err := os.Chmod(path, 0660); err != nil {
- l.Close()
- return nil, err
+
+ for _, op := range opts {
+ if err := op(path); err != nil {
+ _ = l.Close()
+ return nil, err
+ }
}
+
return l, nil
}
+
+// NewUnixSocket creates a unix socket with the specified path and group.
+func NewUnixSocket(path string, gid int) (net.Listener, error) {
+ return NewUnixSocketWithOpts(path, WithChown(0, gid), WithChmod(0660))
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go
index 0ef3fdcb4..992968373 100644
--- a/vendor/github.com/docker/go-connections/tlsconfig/config.go
+++ b/vendor/github.com/docker/go-connections/tlsconfig/config.go
@@ -53,18 +53,9 @@ var acceptedCBCCiphers = []uint16{
// known weak algorithms removed.
var DefaultServerAcceptedCiphers = append(clientCipherSuites, acceptedCBCCiphers...)
-// allTLSVersions lists all the TLS versions and is used by the code that validates
-// a uint16 value as a TLS version.
-var allTLSVersions = map[uint16]struct{}{
- tls.VersionSSL30: {},
- tls.VersionTLS10: {},
- tls.VersionTLS11: {},
- tls.VersionTLS12: {},
-}
-
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
func ServerDefault(ops ...func(*tls.Config)) *tls.Config {
- tlsconfig := &tls.Config{
+ tlsConfig := &tls.Config{
// Avoid fallback by default to SSL protocols < TLS1.2
MinVersion: tls.VersionTLS12,
PreferServerCipherSuites: true,
@@ -72,25 +63,25 @@ func ServerDefault(ops ...func(*tls.Config)) *tls.Config {
}
for _, op := range ops {
- op(tlsconfig)
+ op(tlsConfig)
}
- return tlsconfig
+ return tlsConfig
}
// ClientDefault returns a secure-enough TLS configuration for the client TLS configuration.
func ClientDefault(ops ...func(*tls.Config)) *tls.Config {
- tlsconfig := &tls.Config{
+ tlsConfig := &tls.Config{
// Prefer TLS1.2 as the client minimum
MinVersion: tls.VersionTLS12,
CipherSuites: clientCipherSuites,
}
for _, op := range ops {
- op(tlsconfig)
+ op(tlsConfig)
}
- return tlsconfig
+ return tlsConfig
}
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
@@ -108,11 +99,11 @@ func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
return nil, fmt.Errorf("failed to read system certificates: %v", err)
}
}
- pem, err := ioutil.ReadFile(caFile)
+ pemData, err := ioutil.ReadFile(caFile)
if err != nil {
return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
}
- if !certPool.AppendCertsFromPEM(pem) {
+ if !certPool.AppendCertsFromPEM(pemData) {
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
}
return certPool, nil
@@ -141,7 +132,7 @@ func adjustMinVersion(options Options, config *tls.Config) error {
}
// IsErrEncryptedKey returns true if the 'err' is an error of incorrect
-// password when tryin to decrypt a TLS private key
+// password when trying to decrypt a TLS private key
func IsErrEncryptedKey(err error) bool {
return errors.Cause(err) == x509.IncorrectPasswordError
}
@@ -157,8 +148,8 @@ func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) {
}
var err error
- if x509.IsEncryptedPEMBlock(pemBlock) {
- keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase))
+ if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // Ignore SA1019 (IsEncryptedPEMBlock is deprecated)
+ keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) //nolint:staticcheck // Ignore SA1019 (DecryptPEMBlock is deprecated)
if err != nil {
return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it")
}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/versions_go113.go b/vendor/github.com/docker/go-connections/tlsconfig/versions_go113.go
new file mode 100644
index 000000000..d8215f8e7
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/tlsconfig/versions_go113.go
@@ -0,0 +1,16 @@
+// +build go1.13
+
+package tlsconfig
+
+import (
+ "crypto/tls"
+)
+
+// allTLSVersions lists all the TLS versions and is used by the code that validates
+// a uint16 value as a TLS version.
+var allTLSVersions = map[uint16]struct{}{
+ tls.VersionTLS10: {},
+ tls.VersionTLS11: {},
+ tls.VersionTLS12: {},
+ tls.VersionTLS13: {},
+}
diff --git a/vendor/github.com/docker/go-connections/tlsconfig/versions_other.go b/vendor/github.com/docker/go-connections/tlsconfig/versions_other.go
new file mode 100644
index 000000000..a5ba7f4a3
--- /dev/null
+++ b/vendor/github.com/docker/go-connections/tlsconfig/versions_other.go
@@ -0,0 +1,15 @@
+// +build !go1.13
+
+package tlsconfig
+
+import (
+ "crypto/tls"
+)
+
+// allTLSVersions lists all the TLS versions and is used by the code that validates
+// a uint16 value as a TLS version.
+var allTLSVersions = map[uint16]struct{}{
+ tls.VersionTLS10: {},
+ tls.VersionTLS11: {},
+ tls.VersionTLS12: {},
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/volume/api.go b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
index dcc2f3abf..387e82ac5 100644
--- a/vendor/github.com/docker/go-plugins-helpers/volume/api.go
+++ b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
@@ -1,7 +1,6 @@
package volume
import (
- "log"
"net/http"
"github.com/docker/go-plugins-helpers/sdk"
@@ -130,7 +129,6 @@ func NewHandler(driver Driver) *Handler {
func (h *Handler) initMux() {
h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers createPath")
req := &CreateRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -144,7 +142,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers removePath")
req := &RemoveRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -158,7 +155,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers mountPath")
req := &MountRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -172,7 +168,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers hostVirtualPath")
req := &PathRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -186,7 +181,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers getPath")
req := &GetRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -200,7 +194,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers unmountPath")
req := &UnmountRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -214,7 +207,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers listPath")
res, err := h.driver.List()
if err != nil {
sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
@@ -224,7 +216,6 @@ func (h *Handler) initMux() {
})
h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers capabilitiesPath")
sdk.EncodeResponse(w, h.driver.Capabilities(), false)
})
}
diff --git a/vendor/github.com/docker/libnetwork/ipamutils/utils.go b/vendor/github.com/docker/libnetwork/ipamutils/utils.go
new file mode 100644
index 000000000..3fd37cd88
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/ipamutils/utils.go
@@ -0,0 +1,135 @@
+// Package ipamutils provides utility functions for ipam management
+package ipamutils
+
+import (
+ "fmt"
+ "net"
+ "sync"
+)
+
+var (
+ // PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
+ // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks`
+ PredefinedLocalScopeDefaultNetworks []*net.IPNet
+ // PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8
+ // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks`
+ PredefinedGlobalScopeDefaultNetworks []*net.IPNet
+ mutex sync.Mutex
+ localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
+ {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
+ {"192.168.0.0/16", 20}}
+ globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
+)
+
+// NetworkToSplit represent a network that has to be split in chunks with mask length Size.
+// Each subnet in the set is derived from the Base pool. Base is to be passed
+// in CIDR format.
+// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
+// 10.10.[0-255].0/24 address pools
+type NetworkToSplit struct {
+ Base string `json:"base"`
+ Size int `json:"size"`
+}
+
+func init() {
+ var err error
+ if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil {
+ //we are going to panic in case of error as we should never get into this state
+ panic("InitAddressPools failed to initialize the global scope default address pool")
+ }
+
+ if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil {
+ //we are going to panic in case of error as we should never get into this state
+ panic("InitAddressPools failed to initialize the local scope default address pool")
+ }
+}
+
+// configDefaultNetworks configures local as well global default pool based on input
+func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error {
+ mutex.Lock()
+ defer mutex.Unlock()
+ defaultNetworks, err := splitNetworks(defaultAddressPool)
+ if err != nil {
+ return err
+ }
+ *result = defaultNetworks
+ return nil
+}
+
+// GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks
+func GetGlobalScopeDefaultNetworks() []*net.IPNet {
+ mutex.Lock()
+ defer mutex.Unlock()
+ return PredefinedGlobalScopeDefaultNetworks
+}
+
+// GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks
+func GetLocalScopeDefaultNetworks() []*net.IPNet {
+ mutex.Lock()
+ defer mutex.Unlock()
+ return PredefinedLocalScopeDefaultNetworks
+}
+
+// ConfigGlobalScopeDefaultNetworks configures global default pool.
+// Ideally this will be called from SwarmKit as part of swarm init
+func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
+ if defaultAddressPool == nil {
+ defaultAddressPool = globalScopeDefaultNetworks
+ }
+ return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks)
+}
+
+// ConfigLocalScopeDefaultNetworks configures local default pool.
+// Ideally this will be called during libnetwork init
+func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
+ if defaultAddressPool == nil {
+ return nil
+ }
+ return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks)
+}
+
+// splitNetworks takes a slice of networks, split them accordingly and returns them
+func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
+ localPools := make([]*net.IPNet, 0, len(list))
+
+ for _, p := range list {
+ _, b, err := net.ParseCIDR(p.Base)
+ if err != nil {
+ return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err)
+ }
+ ones, _ := b.Mask.Size()
+ if p.Size <= 0 || p.Size < ones {
+ return nil, fmt.Errorf("invalid pools size: %d", p.Size)
+ }
+ localPools = append(localPools, splitNetwork(p.Size, b)...)
+ }
+ return localPools, nil
+}
+
+func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
+ one, bits := base.Mask.Size()
+ mask := net.CIDRMask(size, bits)
+ n := 1 << uint(size-one)
+ s := uint(bits - size)
+ list := make([]*net.IPNet, 0, n)
+
+ for i := 0; i < n; i++ {
+ ip := copyIP(base.IP)
+ addIntToIP(ip, uint(i<<s))
+ list = append(list, &net.IPNet{IP: ip, Mask: mask})
+ }
+ return list
+}
+
+func copyIP(from net.IP) net.IP {
+ ip := make([]byte, len(from))
+ copy(ip, from)
+ return ip
+}
+
+func addIntToIP(array net.IP, ordinal uint) {
+ for i := len(array) - 1; i >= 0; i-- {
+ array[i] |= (byte)(ordinal & 0xff)
+ ordinal >>= 8
+ }
+}
diff --git a/vendor/github.com/felixge/httpsnoop/.gitignore b/vendor/github.com/felixge/httpsnoop/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/.gitignore
diff --git a/vendor/github.com/felixge/httpsnoop/.travis.yml b/vendor/github.com/felixge/httpsnoop/.travis.yml
new file mode 100644
index 000000000..bfc421200
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/.travis.yml
@@ -0,0 +1,6 @@
+language: go
+
+go:
+ - 1.6
+ - 1.7
+ - 1.8
diff --git a/vendor/github.com/felixge/httpsnoop/LICENSE.txt b/vendor/github.com/felixge/httpsnoop/LICENSE.txt
new file mode 100644
index 000000000..e028b46a9
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2016 Felix Geisendörfer (felix@debuggable.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/vendor/github.com/felixge/httpsnoop/Makefile b/vendor/github.com/felixge/httpsnoop/Makefile
new file mode 100644
index 000000000..2d84889ae
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/Makefile
@@ -0,0 +1,10 @@
+.PHONY: ci generate clean
+
+ci: clean generate
+ go test -v ./...
+
+generate:
+ go generate .
+
+clean:
+ rm -rf *_generated*.go
diff --git a/vendor/github.com/felixge/httpsnoop/README.md b/vendor/github.com/felixge/httpsnoop/README.md
new file mode 100644
index 000000000..ae44137e9
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/README.md
@@ -0,0 +1,94 @@
+# httpsnoop
+
+Package httpsnoop provides an easy way to capture http related metrics (i.e.
+response time, bytes written, and http status code) from your application's
+http.Handlers.
+
+Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
+which is also exposed for users interested in a more low-level API.
+
+[![GoDoc](https://godoc.org/github.com/felixge/httpsnoop?status.svg)](https://godoc.org/github.com/felixge/httpsnoop)
+[![Build Status](https://travis-ci.org/felixge/httpsnoop.svg?branch=master)](https://travis-ci.org/felixge/httpsnoop)
+
+## Usage Example
+
+```go
+// myH is your app's http handler, perhaps a http.ServeMux or similar.
+var myH http.Handler
+// wrappedH wraps myH in order to log every request.
+wrappedH := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ m := httpsnoop.CaptureMetrics(myH, w, r)
+ log.Printf(
+ "%s %s (code=%d dt=%s written=%d)",
+ r.Method,
+ r.URL,
+ m.Code,
+ m.Duration,
+ m.Written,
+ )
+})
+http.ListenAndServe(":8080", wrappedH)
+```
+
+## Why this package exists
+
+Instrumenting an application's http.Handler is surprisingly difficult.
+
+However if you google for e.g. "capture ResponseWriter status code" you'll find
+lots of advise and code examples that suggest it to be a fairly trivial
+undertaking. Unfortunately everything I've seen so far has a high chance of
+breaking your application.
+
+The main problem is that a `http.ResponseWriter` often implements additional
+interfaces such as `http.Flusher`, `http.CloseNotifier`, `http.Hijacker`, `http.Pusher`, and
+`io.ReaderFrom`. So the naive approach of just wrapping `http.ResponseWriter`
+in your own struct that also implements the `http.ResponseWriter` interface
+will hide the additional interfaces mentioned above. This has a high change of
+introducing subtle bugs into any non-trivial application.
+
+Another approach I've seen people take is to return a struct that implements
+all of the interfaces above. However, that's also problematic, because it's
+difficult to fake some of these interfaces behaviors when the underlying
+`http.ResponseWriter` doesn't have an implementation. It's also dangerous,
+because an application may choose to operate differently, merely because it
+detects the presence of these additional interfaces.
+
+This package solves this problem by checking which additional interfaces a
+`http.ResponseWriter` implements, returning a wrapped version implementing the
+exact same set of interfaces.
+
+Additionally this package properly handles edge cases such as `WriteHeader` not
+being called, or called more than once, as well as concurrent calls to
+`http.ResponseWriter` methods, and even calls happening after the wrapped
+`ServeHTTP` has already returned.
+
+Unfortunately this package is not perfect either. It's possible that it is
+still missing some interfaces provided by the go core (let me know if you find
+one), and it won't work for applications adding their own interfaces into the
+mix.
+
+However, hopefully the explanation above has sufficiently scared you of rolling
+your own solution to this problem. httpsnoop may still break your application,
+but at least it tries to avoid it as much as possible.
+
+Anyway, the real problem here is that smuggling additional interfaces inside
+`http.ResponseWriter` is a problematic design choice, but it probably goes as
+deep as the Go language specification itself. But that's okay, I still prefer
+Go over the alternatives ;).
+
+## Performance
+
+```
+BenchmarkBaseline-8 20000 94912 ns/op
+BenchmarkCaptureMetrics-8 20000 95461 ns/op
+```
+
+As you can see, using `CaptureMetrics` on a vanilla http.Handler introduces an
+overhead of ~500 ns per http request on my machine. However, the margin of
+error appears to be larger than that, therefor it should be reasonable to
+assume that the overhead introduced by `CaptureMetrics` is absolutely
+negligible.
+
+## License
+
+MIT
diff --git a/vendor/github.com/felixge/httpsnoop/capture_metrics.go b/vendor/github.com/felixge/httpsnoop/capture_metrics.go
new file mode 100644
index 000000000..4c45b1a8c
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/capture_metrics.go
@@ -0,0 +1,84 @@
+package httpsnoop
+
+import (
+ "io"
+ "net/http"
+ "sync"
+ "time"
+)
+
+// Metrics holds metrics captured from CaptureMetrics.
+type Metrics struct {
+ // Code is the first http response code passed to the WriteHeader func of
+ // the ResponseWriter. If no such call is made, a default code of 200 is
+ // assumed instead.
+ Code int
+ // Duration is the time it took to execute the handler.
+ Duration time.Duration
+ // Written is the number of bytes successfully written by the Write or
+ // ReadFrom function of the ResponseWriter. ResponseWriters may also write
+ // data to their underlaying connection directly (e.g. headers), but those
+ // are not tracked. Therefor the number of Written bytes will usually match
+ // the size of the response body.
+ Written int64
+}
+
+// CaptureMetrics wraps the given hnd, executes it with the given w and r, and
+// returns the metrics it captured from it.
+func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Metrics {
+ return CaptureMetricsFn(w, func(ww http.ResponseWriter) {
+ hnd.ServeHTTP(ww, r)
+ })
+}
+
+// CaptureMetricsFn wraps w and calls fn with the wrapped w and returns the
+// resulting metrics. This is very similar to CaptureMetrics (which is just
+// sugar on top of this func), but is a more usable interface if your
+// application doesn't use the Go http.Handler interface.
+func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics {
+ var (
+ start = time.Now()
+ m = Metrics{Code: http.StatusOK}
+ headerWritten bool
+ lock sync.Mutex
+ hooks = Hooks{
+ WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc {
+ return func(code int) {
+ next(code)
+ lock.Lock()
+ defer lock.Unlock()
+ if !headerWritten {
+ m.Code = code
+ headerWritten = true
+ }
+ }
+ },
+
+ Write: func(next WriteFunc) WriteFunc {
+ return func(p []byte) (int, error) {
+ n, err := next(p)
+ lock.Lock()
+ defer lock.Unlock()
+ m.Written += int64(n)
+ headerWritten = true
+ return n, err
+ }
+ },
+
+ ReadFrom: func(next ReadFromFunc) ReadFromFunc {
+ return func(src io.Reader) (int64, error) {
+ n, err := next(src)
+ lock.Lock()
+ defer lock.Unlock()
+ headerWritten = true
+ m.Written += n
+ return n, err
+ }
+ },
+ }
+ )
+
+ fn(Wrap(w, hooks))
+ m.Duration = time.Since(start)
+ return m
+}
diff --git a/vendor/github.com/felixge/httpsnoop/docs.go b/vendor/github.com/felixge/httpsnoop/docs.go
new file mode 100644
index 000000000..203c35b3c
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/docs.go
@@ -0,0 +1,10 @@
+// Package httpsnoop provides an easy way to capture http related metrics (i.e.
+// response time, bytes written, and http status code) from your application's
+// http.Handlers.
+//
+// Doing this requires non-trivial wrapping of the http.ResponseWriter
+// interface, which is also exposed for users interested in a more low-level
+// API.
+package httpsnoop
+
+//go:generate go run codegen/main.go
diff --git a/vendor/github.com/felixge/httpsnoop/go.mod b/vendor/github.com/felixge/httpsnoop/go.mod
new file mode 100644
index 000000000..73b394690
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/go.mod
@@ -0,0 +1,3 @@
+module github.com/felixge/httpsnoop
+
+go 1.13
diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
new file mode 100644
index 000000000..41a20da9e
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
@@ -0,0 +1,385 @@
+// +build go1.8
+// Code generated by "httpsnoop/codegen"; DO NOT EDIT
+
+package httpsnoop
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+// HeaderFunc is part of the http.ResponseWriter interface.
+type HeaderFunc func() http.Header
+
+// WriteHeaderFunc is part of the http.ResponseWriter interface.
+type WriteHeaderFunc func(code int)
+
+// WriteFunc is part of the http.ResponseWriter interface.
+type WriteFunc func(b []byte) (int, error)
+
+// FlushFunc is part of the http.Flusher interface.
+type FlushFunc func()
+
+// CloseNotifyFunc is part of the http.CloseNotifier interface.
+type CloseNotifyFunc func() <-chan bool
+
+// HijackFunc is part of the http.Hijacker interface.
+type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
+
+// ReadFromFunc is part of the io.ReaderFrom interface.
+type ReadFromFunc func(src io.Reader) (int64, error)
+
+// PushFunc is part of the http.Pusher interface.
+type PushFunc func(target string, opts *http.PushOptions) error
+
+// Hooks defines a set of method interceptors for methods included in
+// http.ResponseWriter as well as some others. You can think of them as
+// middleware for the function calls they target. See Wrap for more details.
+type Hooks struct {
+ Header func(HeaderFunc) HeaderFunc
+ WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
+ Write func(WriteFunc) WriteFunc
+ Flush func(FlushFunc) FlushFunc
+ CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
+ Hijack func(HijackFunc) HijackFunc
+ ReadFrom func(ReadFromFunc) ReadFromFunc
+ Push func(PushFunc) PushFunc
+}
+
+// Wrap returns a wrapped version of w that provides the exact same interface
+// as w. Specifically if w implements any combination of:
+//
+// - http.Flusher
+// - http.CloseNotifier
+// - http.Hijacker
+// - io.ReaderFrom
+// - http.Pusher
+//
+// The wrapped version will implement the exact same combination. If no hooks
+// are set, the wrapped version also behaves exactly as w. Hooks targeting
+// methods not supported by w are ignored. Any other hooks will intercept the
+// method they target and may modify the call's arguments and/or return values.
+// The CaptureMetrics implementation serves as a working example for how the
+// hooks can be used.
+func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
+ rw := &rw{w: w, h: hooks}
+ _, i0 := w.(http.Flusher)
+ _, i1 := w.(http.CloseNotifier)
+ _, i2 := w.(http.Hijacker)
+ _, i3 := w.(io.ReaderFrom)
+ _, i4 := w.(http.Pusher)
+ switch {
+ // combination 1/32
+ case !i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ }{rw}
+ // combination 2/32
+ case !i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ }{rw, rw}
+ // combination 3/32
+ case !i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{rw, rw}
+ // combination 4/32
+ case !i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 5/32
+ case !i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{rw, rw}
+ // combination 6/32
+ case !i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 7/32
+ case !i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 8/32
+ case !i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 9/32
+ case !i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{rw, rw}
+ // combination 10/32
+ case !i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 11/32
+ case !i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 12/32
+ case !i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 13/32
+ case !i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 14/32
+ case !i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 15/32
+ case !i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 16/32
+ case !i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 17/32
+ case i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{rw, rw}
+ // combination 18/32
+ case i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 19/32
+ case i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 20/32
+ case i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 21/32
+ case i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 22/32
+ case i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 23/32
+ case i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 24/32
+ case i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 25/32
+ case i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ }{rw, rw, rw}
+ // combination 26/32
+ case i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 27/32
+ case i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 28/32
+ case i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 29/32
+ case i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw, rw}
+ // combination 30/32
+ case i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 31/32
+ case i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw, rw}
+ // combination 32/32
+ case i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw, rw}
+ }
+ panic("unreachable")
+}
+
+type rw struct {
+ w http.ResponseWriter
+ h Hooks
+}
+
+func (w *rw) Header() http.Header {
+ f := w.w.(http.ResponseWriter).Header
+ if w.h.Header != nil {
+ f = w.h.Header(f)
+ }
+ return f()
+}
+
+func (w *rw) WriteHeader(code int) {
+ f := w.w.(http.ResponseWriter).WriteHeader
+ if w.h.WriteHeader != nil {
+ f = w.h.WriteHeader(f)
+ }
+ f(code)
+}
+
+func (w *rw) Write(b []byte) (int, error) {
+ f := w.w.(http.ResponseWriter).Write
+ if w.h.Write != nil {
+ f = w.h.Write(f)
+ }
+ return f(b)
+}
+
+func (w *rw) Flush() {
+ f := w.w.(http.Flusher).Flush
+ if w.h.Flush != nil {
+ f = w.h.Flush(f)
+ }
+ f()
+}
+
+func (w *rw) CloseNotify() <-chan bool {
+ f := w.w.(http.CloseNotifier).CloseNotify
+ if w.h.CloseNotify != nil {
+ f = w.h.CloseNotify(f)
+ }
+ return f()
+}
+
+func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ f := w.w.(http.Hijacker).Hijack
+ if w.h.Hijack != nil {
+ f = w.h.Hijack(f)
+ }
+ return f()
+}
+
+func (w *rw) ReadFrom(src io.Reader) (int64, error) {
+ f := w.w.(io.ReaderFrom).ReadFrom
+ if w.h.ReadFrom != nil {
+ f = w.h.ReadFrom(f)
+ }
+ return f(src)
+}
+
+func (w *rw) Push(target string, opts *http.PushOptions) error {
+ f := w.w.(http.Pusher).Push
+ if w.h.Push != nil {
+ f = w.h.Push(f)
+ }
+ return f(target, opts)
+}
diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
new file mode 100644
index 000000000..36bb59b83
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
@@ -0,0 +1,243 @@
+// +build !go1.8
+// Code generated by "httpsnoop/codegen"; DO NOT EDIT
+
+package httpsnoop
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+// HeaderFunc is part of the http.ResponseWriter interface.
+type HeaderFunc func() http.Header
+
+// WriteHeaderFunc is part of the http.ResponseWriter interface.
+type WriteHeaderFunc func(code int)
+
+// WriteFunc is part of the http.ResponseWriter interface.
+type WriteFunc func(b []byte) (int, error)
+
+// FlushFunc is part of the http.Flusher interface.
+type FlushFunc func()
+
+// CloseNotifyFunc is part of the http.CloseNotifier interface.
+type CloseNotifyFunc func() <-chan bool
+
+// HijackFunc is part of the http.Hijacker interface.
+type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
+
+// ReadFromFunc is part of the io.ReaderFrom interface.
+type ReadFromFunc func(src io.Reader) (int64, error)
+
+// Hooks defines a set of method interceptors for methods included in
+// http.ResponseWriter as well as some others. You can think of them as
+// middleware for the function calls they target. See Wrap for more details.
+type Hooks struct {
+ Header func(HeaderFunc) HeaderFunc
+ WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
+ Write func(WriteFunc) WriteFunc
+ Flush func(FlushFunc) FlushFunc
+ CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
+ Hijack func(HijackFunc) HijackFunc
+ ReadFrom func(ReadFromFunc) ReadFromFunc
+}
+
+// Wrap returns a wrapped version of w that provides the exact same interface
+// as w. Specifically if w implements any combination of:
+//
+// - http.Flusher
+// - http.CloseNotifier
+// - http.Hijacker
+// - io.ReaderFrom
+//
+// The wrapped version will implement the exact same combination. If no hooks
+// are set, the wrapped version also behaves exactly as w. Hooks targeting
+// methods not supported by w are ignored. Any other hooks will intercept the
+// method they target and may modify the call's arguments and/or return values.
+// The CaptureMetrics implementation serves as a working example for how the
+// hooks can be used.
+func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
+ rw := &rw{w: w, h: hooks}
+ _, i0 := w.(http.Flusher)
+ _, i1 := w.(http.CloseNotifier)
+ _, i2 := w.(http.Hijacker)
+ _, i3 := w.(io.ReaderFrom)
+ switch {
+ // combination 1/16
+ case !i0 && !i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ }{rw}
+ // combination 2/16
+ case !i0 && !i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{rw, rw}
+ // combination 3/16
+ case !i0 && !i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{rw, rw}
+ // combination 4/16
+ case !i0 && !i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 5/16
+ case !i0 && i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{rw, rw}
+ // combination 6/16
+ case !i0 && i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 7/16
+ case !i0 && i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 8/16
+ case !i0 && i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 9/16
+ case i0 && !i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{rw, rw}
+ // combination 10/16
+ case i0 && !i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 11/16
+ case i0 && !i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 12/16
+ case i0 && !i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 13/16
+ case i0 && i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ }{rw, rw, rw}
+ // combination 14/16
+ case i0 && i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 15/16
+ case i0 && i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw, rw}
+ // combination 16/16
+ case i0 && i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw, rw}
+ }
+ panic("unreachable")
+}
+
+type rw struct {
+ w http.ResponseWriter
+ h Hooks
+}
+
+func (w *rw) Header() http.Header {
+ f := w.w.(http.ResponseWriter).Header
+ if w.h.Header != nil {
+ f = w.h.Header(f)
+ }
+ return f()
+}
+
+func (w *rw) WriteHeader(code int) {
+ f := w.w.(http.ResponseWriter).WriteHeader
+ if w.h.WriteHeader != nil {
+ f = w.h.WriteHeader(f)
+ }
+ f(code)
+}
+
+func (w *rw) Write(b []byte) (int, error) {
+ f := w.w.(http.ResponseWriter).Write
+ if w.h.Write != nil {
+ f = w.h.Write(f)
+ }
+ return f(b)
+}
+
+func (w *rw) Flush() {
+ f := w.w.(http.Flusher).Flush
+ if w.h.Flush != nil {
+ f = w.h.Flush(f)
+ }
+ f()
+}
+
+func (w *rw) CloseNotify() <-chan bool {
+ f := w.w.(http.CloseNotifier).CloseNotify
+ if w.h.CloseNotify != nil {
+ f = w.h.CloseNotify(f)
+ }
+ return f()
+}
+
+func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ f := w.w.(http.Hijacker).Hijack
+ if w.h.Hijack != nil {
+ f = w.h.Hijack(f)
+ }
+ return f()
+}
+
+func (w *rw) ReadFrom(src io.Reader) (int64, error) {
+ f := w.w.(io.ReaderFrom).ReadFrom
+ if w.h.ReadFrom != nil {
+ f = w.h.ReadFrom(f)
+ }
+ return f(src)
+}
diff --git a/vendor/github.com/google/shlex/go.mod b/vendor/github.com/google/shlex/go.mod
new file mode 100644
index 000000000..0ab3bce7f
--- /dev/null
+++ b/vendor/github.com/google/shlex/go.mod
@@ -0,0 +1,3 @@
+module github.com/google/shlex
+
+go 1.13
diff --git a/vendor/github.com/gorilla/handlers/.travis.yml b/vendor/github.com/gorilla/handlers/.travis.yml
deleted file mode 100644
index 354b7f8b2..000000000
--- a/vendor/github.com/gorilla/handlers/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: go
-
-go:
- - 1.1
- - 1.2
- - 1.3
- - 1.4
- - tip
diff --git a/vendor/github.com/gorilla/handlers/README.md b/vendor/github.com/gorilla/handlers/README.md
index a340abe08..6eba66bf3 100644
--- a/vendor/github.com/gorilla/handlers/README.md
+++ b/vendor/github.com/gorilla/handlers/README.md
@@ -1,28 +1,32 @@
gorilla/handlers
================
-[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers)
+[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers)
+[![CircleCI](https://circleci.com/gh/gorilla/handlers.svg?style=svg)](https://circleci.com/gh/gorilla/handlers)
+[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge)
+
Package handlers is a collection of handlers (aka "HTTP middleware") for use
with Go's `net/http` package (or any framework supporting `http.Handler`), including:
-* `LoggingHandler` for logging HTTP requests in the Apache [Common Log
+* [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log
Format](http://httpd.apache.org/docs/2.2/logs.html#common).
-* `CombinedLoggingHandler` for logging HTTP requests in the Apache [Combined Log
+* [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log
Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
both Apache and nginx.
-* `CompressHandler` for gzipping responses.
-* `ContentTypeHandler` for validating requests against a list of accepted
+* [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses.
+* [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted
content types.
-* `MethodHandler` for matching HTTP methods against handlers in a
+* [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a
`map[string]http.Handler`
-* `ProxyHeaders` for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
+* [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
headers when running a Go server behind a HTTP reverse proxy.
-* `CanonicalHost` for re-directing to the preferred host when handling multiple
+* [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple
domains (i.e. multiple CNAME aliases).
+* [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics.
Other handlers are documented [on the Gorilla
-website](http://www.gorillatoolkit.org/pkg/handlers).
+website](https://www.gorillatoolkit.org/pkg/handlers).
## Example
diff --git a/vendor/github.com/gorilla/handlers/canonical.go b/vendor/github.com/gorilla/handlers/canonical.go
index 3961695c4..8437fefc1 100644
--- a/vendor/github.com/gorilla/handlers/canonical.go
+++ b/vendor/github.com/gorilla/handlers/canonical.go
@@ -18,7 +18,6 @@ type canonical struct {
//
// Note: If the provided domain is considered invalid by url.Parse or otherwise
// returns an empty scheme or host, clients are not re-directed.
-// not re-directed.
//
// Example:
//
@@ -54,7 +53,11 @@ func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
// Re-build the destination URL
dest := dest.Scheme + "://" + dest.Host + r.URL.Path
+ if r.URL.RawQuery != "" {
+ dest += "?" + r.URL.RawQuery
+ }
http.Redirect(w, r, dest, c.code)
+ return
}
c.h.ServeHTTP(w, r)
diff --git a/vendor/github.com/gorilla/handlers/compress.go b/vendor/github.com/gorilla/handlers/compress.go
index 3d90e1914..1e95f1ccb 100644
--- a/vendor/github.com/gorilla/handlers/compress.go
+++ b/vendor/github.com/gorilla/handlers/compress.go
@@ -10,75 +10,134 @@ import (
"io"
"net/http"
"strings"
+
+ "github.com/felixge/httpsnoop"
)
+const acceptEncoding string = "Accept-Encoding"
+
type compressResponseWriter struct {
- io.Writer
- http.ResponseWriter
- http.Hijacker
+ compressor io.Writer
+ w http.ResponseWriter
}
-func (w *compressResponseWriter) Header() http.Header {
- return w.ResponseWriter.Header()
+func (cw *compressResponseWriter) WriteHeader(c int) {
+ cw.w.Header().Del("Content-Length")
+ cw.w.WriteHeader(c)
}
-func (w *compressResponseWriter) Write(b []byte) (int, error) {
- h := w.ResponseWriter.Header()
+func (cw *compressResponseWriter) Write(b []byte) (int, error) {
+ h := cw.w.Header()
if h.Get("Content-Type") == "" {
h.Set("Content-Type", http.DetectContentType(b))
}
+ h.Del("Content-Length")
+
+ return cw.compressor.Write(b)
+}
- return w.Writer.Write(b)
+func (cw *compressResponseWriter) ReadFrom(r io.Reader) (int64, error) {
+ return io.Copy(cw.compressor, r)
+}
+
+type flusher interface {
+ Flush() error
+}
+
+func (w *compressResponseWriter) Flush() {
+ // Flush compressed data if compressor supports it.
+ if f, ok := w.compressor.(flusher); ok {
+ f.Flush()
+ }
+ // Flush HTTP response.
+ if f, ok := w.w.(http.Flusher); ok {
+ f.Flush()
+ }
}
// CompressHandler gzip compresses HTTP responses for clients that support it
// via the 'Accept-Encoding' header.
+//
+// Compressing TLS traffic may leak the page contents to an attacker if the
+// page contains user input: http://security.stackexchange.com/a/102015/12208
func CompressHandler(h http.Handler) http.Handler {
+ return CompressHandlerLevel(h, gzip.DefaultCompression)
+}
+
+// CompressHandlerLevel gzip compresses HTTP responses with specified compression level
+// for clients that support it via the 'Accept-Encoding' header.
+//
+// The compression level should be gzip.DefaultCompression, gzip.NoCompression,
+// or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive.
+// gzip.DefaultCompression is used in case of invalid compression level.
+func CompressHandlerLevel(h http.Handler, level int) http.Handler {
+ if level < gzip.DefaultCompression || level > gzip.BestCompression {
+ level = gzip.DefaultCompression
+ }
+
+ const (
+ gzipEncoding = "gzip"
+ flateEncoding = "deflate"
+ )
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- L:
- for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
- switch strings.TrimSpace(enc) {
- case "gzip":
- w.Header().Set("Content-Encoding", "gzip")
- w.Header().Add("Vary", "Accept-Encoding")
-
- gw := gzip.NewWriter(w)
- defer gw.Close()
-
- h, hok := w.(http.Hijacker)
- if !hok { /* w is not Hijacker... oh well... */
- h = nil
- }
-
- w = &compressResponseWriter{
- Writer: gw,
- ResponseWriter: w,
- Hijacker: h,
- }
-
- break L
- case "deflate":
- w.Header().Set("Content-Encoding", "deflate")
- w.Header().Add("Vary", "Accept-Encoding")
-
- fw, _ := flate.NewWriter(w, flate.DefaultCompression)
- defer fw.Close()
-
- h, hok := w.(http.Hijacker)
- if !hok { /* w is not Hijacker... oh well... */
- h = nil
- }
-
- w = &compressResponseWriter{
- Writer: fw,
- ResponseWriter: w,
- Hijacker: h,
- }
-
- break L
+ // detect what encoding to use
+ var encoding string
+ for _, curEnc := range strings.Split(r.Header.Get(acceptEncoding), ",") {
+ curEnc = strings.TrimSpace(curEnc)
+ if curEnc == gzipEncoding || curEnc == flateEncoding {
+ encoding = curEnc
+ break
}
}
+ // always add Accept-Encoding to Vary to prevent intermediate caches corruption
+ w.Header().Add("Vary", acceptEncoding)
+
+ // if we weren't able to identify an encoding we're familiar with, pass on the
+ // request to the handler and return
+ if encoding == "" {
+ h.ServeHTTP(w, r)
+ return
+ }
+
+ if r.Header.Get("Upgrade") != "" {
+ h.ServeHTTP(w, r)
+ return
+ }
+
+ // wrap the ResponseWriter with the writer for the chosen encoding
+ var encWriter io.WriteCloser
+ if encoding == gzipEncoding {
+ encWriter, _ = gzip.NewWriterLevel(w, level)
+ } else if encoding == flateEncoding {
+ encWriter, _ = flate.NewWriter(w, level)
+ }
+ defer encWriter.Close()
+
+ w.Header().Set("Content-Encoding", encoding)
+ r.Header.Del(acceptEncoding)
+
+ cw := &compressResponseWriter{
+ w: w,
+ compressor: encWriter,
+ }
+
+ w = httpsnoop.Wrap(w, httpsnoop.Hooks{
+ Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
+ return cw.Write
+ },
+ WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
+ return cw.WriteHeader
+ },
+ Flush: func(httpsnoop.FlushFunc) httpsnoop.FlushFunc {
+ return cw.Flush
+ },
+ ReadFrom: func(rff httpsnoop.ReadFromFunc) httpsnoop.ReadFromFunc {
+ return cw.ReadFrom
+ },
+ })
+
h.ServeHTTP(w, r)
})
}
diff --git a/vendor/github.com/gorilla/handlers/cors.go b/vendor/github.com/gorilla/handlers/cors.go
new file mode 100644
index 000000000..0dcdffb3d
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/cors.go
@@ -0,0 +1,355 @@
+package handlers
+
+import (
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+// CORSOption represents a functional option for configuring the CORS middleware.
+type CORSOption func(*cors) error
+
+type cors struct {
+ h http.Handler
+ allowedHeaders []string
+ allowedMethods []string
+ allowedOrigins []string
+ allowedOriginValidator OriginValidator
+ exposedHeaders []string
+ maxAge int
+ ignoreOptions bool
+ allowCredentials bool
+ optionStatusCode int
+}
+
+// OriginValidator takes an origin string and returns whether or not that origin is allowed.
+type OriginValidator func(string) bool
+
+var (
+ defaultCorsOptionStatusCode = 200
+ defaultCorsMethods = []string{"GET", "HEAD", "POST"}
+ defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
+ // (WebKit/Safari v9 sends the Origin header by default in AJAX requests)
+)
+
+const (
+ corsOptionMethod string = "OPTIONS"
+ corsAllowOriginHeader string = "Access-Control-Allow-Origin"
+ corsExposeHeadersHeader string = "Access-Control-Expose-Headers"
+ corsMaxAgeHeader string = "Access-Control-Max-Age"
+ corsAllowMethodsHeader string = "Access-Control-Allow-Methods"
+ corsAllowHeadersHeader string = "Access-Control-Allow-Headers"
+ corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
+ corsRequestMethodHeader string = "Access-Control-Request-Method"
+ corsRequestHeadersHeader string = "Access-Control-Request-Headers"
+ corsOriginHeader string = "Origin"
+ corsVaryHeader string = "Vary"
+ corsOriginMatchAll string = "*"
+)
+
+func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ origin := r.Header.Get(corsOriginHeader)
+ if !ch.isOriginAllowed(origin) {
+ if r.Method != corsOptionMethod || ch.ignoreOptions {
+ ch.h.ServeHTTP(w, r)
+ }
+
+ return
+ }
+
+ if r.Method == corsOptionMethod {
+ if ch.ignoreOptions {
+ ch.h.ServeHTTP(w, r)
+ return
+ }
+
+ if _, ok := r.Header[corsRequestMethodHeader]; !ok {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ method := r.Header.Get(corsRequestMethodHeader)
+ if !ch.isMatch(method, ch.allowedMethods) {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
+ allowedHeaders := []string{}
+ for _, v := range requestHeaders {
+ canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
+ continue
+ }
+
+ if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ allowedHeaders = append(allowedHeaders, canonicalHeader)
+ }
+
+ if len(allowedHeaders) > 0 {
+ w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
+ }
+
+ if ch.maxAge > 0 {
+ w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
+ }
+
+ if !ch.isMatch(method, defaultCorsMethods) {
+ w.Header().Set(corsAllowMethodsHeader, method)
+ }
+ } else {
+ if len(ch.exposedHeaders) > 0 {
+ w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
+ }
+ }
+
+ if ch.allowCredentials {
+ w.Header().Set(corsAllowCredentialsHeader, "true")
+ }
+
+ if len(ch.allowedOrigins) > 1 {
+ w.Header().Set(corsVaryHeader, corsOriginHeader)
+ }
+
+ returnOrigin := origin
+ if ch.allowedOriginValidator == nil && len(ch.allowedOrigins) == 0 {
+ returnOrigin = "*"
+ } else {
+ for _, o := range ch.allowedOrigins {
+ // A configuration of * is different than explicitly setting an allowed
+ // origin. Returning arbitrary origin headers in an access control allow
+ // origin header is unsafe and is not required by any use case.
+ if o == corsOriginMatchAll {
+ returnOrigin = "*"
+ break
+ }
+ }
+ }
+ w.Header().Set(corsAllowOriginHeader, returnOrigin)
+
+ if r.Method == corsOptionMethod {
+ w.WriteHeader(ch.optionStatusCode)
+ return
+ }
+ ch.h.ServeHTTP(w, r)
+}
+
+// CORS provides Cross-Origin Resource Sharing middleware.
+// Example:
+//
+// import (
+// "net/http"
+//
+// "github.com/gorilla/handlers"
+// "github.com/gorilla/mux"
+// )
+//
+// func main() {
+// r := mux.NewRouter()
+// r.HandleFunc("/users", UserEndpoint)
+// r.HandleFunc("/projects", ProjectEndpoint)
+//
+// // Apply the CORS middleware to our top-level router, with the defaults.
+// http.ListenAndServe(":8000", handlers.CORS()(r))
+// }
+//
+func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
+ return func(h http.Handler) http.Handler {
+ ch := parseCORSOptions(opts...)
+ ch.h = h
+ return ch
+ }
+}
+
+func parseCORSOptions(opts ...CORSOption) *cors {
+ ch := &cors{
+ allowedMethods: defaultCorsMethods,
+ allowedHeaders: defaultCorsHeaders,
+ allowedOrigins: []string{},
+ optionStatusCode: defaultCorsOptionStatusCode,
+ }
+
+ for _, option := range opts {
+ option(ch)
+ }
+
+ return ch
+}
+
+//
+// Functional options for configuring CORS.
+//
+
+// AllowedHeaders adds the provided headers to the list of allowed headers in a
+// CORS request.
+// This is an append operation so the headers Accept, Accept-Language,
+// and Content-Language are always allowed.
+// Content-Type must be explicitly declared if accepting Content-Types other than
+// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
+func AllowedHeaders(headers []string) CORSOption {
+ return func(ch *cors) error {
+ for _, v := range headers {
+ normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if normalizedHeader == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
+ ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
+ }
+ }
+
+ return nil
+ }
+}
+
+// AllowedMethods can be used to explicitly allow methods in the
+// Access-Control-Allow-Methods header.
+// This is a replacement operation so you must also
+// pass GET, HEAD, and POST if you wish to support those methods.
+func AllowedMethods(methods []string) CORSOption {
+ return func(ch *cors) error {
+ ch.allowedMethods = []string{}
+ for _, v := range methods {
+ normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
+ if normalizedMethod == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
+ ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
+ }
+ }
+
+ return nil
+ }
+}
+
+// AllowedOrigins sets the allowed origins for CORS requests, as used in the
+// 'Allow-Access-Control-Origin' HTTP header.
+// Note: Passing in a []string{"*"} will allow any domain.
+func AllowedOrigins(origins []string) CORSOption {
+ return func(ch *cors) error {
+ for _, v := range origins {
+ if v == corsOriginMatchAll {
+ ch.allowedOrigins = []string{corsOriginMatchAll}
+ return nil
+ }
+ }
+
+ ch.allowedOrigins = origins
+ return nil
+ }
+}
+
+// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
+// 'Allow-Access-Control-Origin' HTTP header.
+func AllowedOriginValidator(fn OriginValidator) CORSOption {
+ return func(ch *cors) error {
+ ch.allowedOriginValidator = fn
+ return nil
+ }
+}
+
+// OptionStatusCode sets a custom status code on the OPTIONS requests.
+// Default behaviour sets it to 200 to reflect best practices. This is option is not mandatory
+// and can be used if you need a custom status code (i.e 204).
+//
+// More informations on the spec:
+// https://fetch.spec.whatwg.org/#cors-preflight-fetch
+func OptionStatusCode(code int) CORSOption {
+ return func(ch *cors) error {
+ ch.optionStatusCode = code
+ return nil
+ }
+}
+
+// ExposedHeaders can be used to specify headers that are available
+// and will not be stripped out by the user-agent.
+func ExposedHeaders(headers []string) CORSOption {
+ return func(ch *cors) error {
+ ch.exposedHeaders = []string{}
+ for _, v := range headers {
+ normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if normalizedHeader == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
+ ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
+ }
+ }
+
+ return nil
+ }
+}
+
+// MaxAge determines the maximum age (in seconds) between preflight requests. A
+// maximum of 10 minutes is allowed. An age above this value will default to 10
+// minutes.
+func MaxAge(age int) CORSOption {
+ return func(ch *cors) error {
+ // Maximum of 10 minutes.
+ if age > 600 {
+ age = 600
+ }
+
+ ch.maxAge = age
+ return nil
+ }
+}
+
+// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
+// passing them through to the next handler. This is useful when your application
+// or framework has a pre-existing mechanism for responding to OPTIONS requests.
+func IgnoreOptions() CORSOption {
+ return func(ch *cors) error {
+ ch.ignoreOptions = true
+ return nil
+ }
+}
+
+// AllowCredentials can be used to specify that the user agent may pass
+// authentication details along with the request.
+func AllowCredentials() CORSOption {
+ return func(ch *cors) error {
+ ch.allowCredentials = true
+ return nil
+ }
+}
+
+func (ch *cors) isOriginAllowed(origin string) bool {
+ if origin == "" {
+ return false
+ }
+
+ if ch.allowedOriginValidator != nil {
+ return ch.allowedOriginValidator(origin)
+ }
+
+ if len(ch.allowedOrigins) == 0 {
+ return true
+ }
+
+ for _, allowedOrigin := range ch.allowedOrigins {
+ if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (ch *cors) isMatch(needle string, haystack []string) bool {
+ for _, v := range haystack {
+ if v == needle {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/github.com/gorilla/handlers/go.mod b/vendor/github.com/gorilla/handlers/go.mod
new file mode 100644
index 000000000..58e6a85ec
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/go.mod
@@ -0,0 +1,5 @@
+module github.com/gorilla/handlers
+
+go 1.14
+
+require github.com/felixge/httpsnoop v1.0.1
diff --git a/vendor/github.com/gorilla/handlers/go.sum b/vendor/github.com/gorilla/handlers/go.sum
new file mode 100644
index 000000000..8c2645804
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/go.sum
@@ -0,0 +1,2 @@
+github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
diff --git a/vendor/github.com/gorilla/handlers/handlers.go b/vendor/github.com/gorilla/handlers/handlers.go
index c3c20e5b9..0509482ad 100644
--- a/vendor/github.com/gorilla/handlers/handlers.go
+++ b/vendor/github.com/gorilla/handlers/handlers.go
@@ -7,27 +7,22 @@ package handlers
import (
"bufio"
"fmt"
- "io"
"net"
"net/http"
- "net/url"
"sort"
- "strconv"
"strings"
- "time"
- "unicode/utf8"
)
-// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
-// map matches the name of the HTTP request's method, eg: GET
+// MethodHandler is an http.Handler that dispatches to a handler whose key in the
+// MethodHandler's map matches the name of the HTTP request's method, eg: GET
//
-// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
-// responds with a status of 200 and sets the Allow header to a comma-separated list of
-// available methods.
+// If the request's method is OPTIONS and OPTIONS is not a key in the map then
+// the handler responds with a status of 200 and sets the Allow header to a
+// comma-separated list of available methods.
//
-// If the request's method doesn't match any of its keys the handler responds with
-// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
-// of available methods.
+// If the request's method doesn't match any of its keys the handler responds
+// with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
+// comma-separated list of available methods.
type MethodHandler map[string]http.Handler
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
@@ -48,74 +43,15 @@ func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
-// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
-type loggingHandler struct {
- writer io.Writer
- handler http.Handler
-}
-
-// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
-type combinedLoggingHandler struct {
- writer io.Writer
- handler http.Handler
-}
-
-func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- t := time.Now()
- logger := makeLogger(w)
- url := *req.URL
- h.handler.ServeHTTP(logger, req)
- writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
-}
-
-func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- t := time.Now()
- logger := makeLogger(w)
- url := *req.URL
- h.handler.ServeHTTP(logger, req)
- writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
-}
-
-func makeLogger(w http.ResponseWriter) loggingResponseWriter {
- var logger loggingResponseWriter = &responseLogger{w: w}
- if _, ok := w.(http.Hijacker); ok {
- logger = &hijackLogger{responseLogger{w: w}}
- }
- h, ok1 := logger.(http.Hijacker)
- c, ok2 := w.(http.CloseNotifier)
- if ok1 && ok2 {
- return hijackCloseNotifier{logger, h, c}
- }
- if ok2 {
- return &closeNotifyWriter{logger, c}
- }
- return logger
-}
-
-type loggingResponseWriter interface {
- http.ResponseWriter
- http.Flusher
- Status() int
- Size() int
-}
-
-// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
-// code and body size
+// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
+// status code and body size
type responseLogger struct {
w http.ResponseWriter
status int
size int
}
-func (l *responseLogger) Header() http.Header {
- return l.w.Header()
-}
-
func (l *responseLogger) Write(b []byte) (int, error) {
- if l.status == 0 {
- // The status will be StatusOK if WriteHeader has not been called yet
- l.status = http.StatusOK
- }
size, err := l.w.Write(b)
l.size += size
return size, err
@@ -134,187 +70,18 @@ func (l *responseLogger) Size() int {
return l.size
}
-func (l *responseLogger) Flush() {
- f, ok := l.w.(http.Flusher)
- if ok {
- f.Flush()
- }
-}
-
-type hijackLogger struct {
- responseLogger
-}
-
-func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
- h := l.responseLogger.w.(http.Hijacker)
- conn, rw, err := h.Hijack()
- if err == nil && l.responseLogger.status == 0 {
- // The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
- l.responseLogger.status = http.StatusSwitchingProtocols
+func (l *responseLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ conn, rw, err := l.w.(http.Hijacker).Hijack()
+ if err == nil && l.status == 0 {
+ // The status will be StatusSwitchingProtocols if there was no error and
+ // WriteHeader has not been called yet
+ l.status = http.StatusSwitchingProtocols
}
return conn, rw, err
}
-type closeNotifyWriter struct {
- loggingResponseWriter
- http.CloseNotifier
-}
-
-type hijackCloseNotifier struct {
- loggingResponseWriter
- http.Hijacker
- http.CloseNotifier
-}
-
-const lowerhex = "0123456789abcdef"
-
-func appendQuoted(buf []byte, s string) []byte {
- var runeTmp [utf8.UTFMax]byte
- for width := 0; len(s) > 0; s = s[width:] {
- r := rune(s[0])
- width = 1
- if r >= utf8.RuneSelf {
- r, width = utf8.DecodeRuneInString(s)
- }
- if width == 1 && r == utf8.RuneError {
- buf = append(buf, `\x`...)
- buf = append(buf, lowerhex[s[0]>>4])
- buf = append(buf, lowerhex[s[0]&0xF])
- continue
- }
- if r == rune('"') || r == '\\' { // always backslashed
- buf = append(buf, '\\')
- buf = append(buf, byte(r))
- continue
- }
- if strconv.IsPrint(r) {
- n := utf8.EncodeRune(runeTmp[:], r)
- buf = append(buf, runeTmp[:n]...)
- continue
- }
- switch r {
- case '\a':
- buf = append(buf, `\a`...)
- case '\b':
- buf = append(buf, `\b`...)
- case '\f':
- buf = append(buf, `\f`...)
- case '\n':
- buf = append(buf, `\n`...)
- case '\r':
- buf = append(buf, `\r`...)
- case '\t':
- buf = append(buf, `\t`...)
- case '\v':
- buf = append(buf, `\v`...)
- default:
- switch {
- case r < ' ':
- buf = append(buf, `\x`...)
- buf = append(buf, lowerhex[s[0]>>4])
- buf = append(buf, lowerhex[s[0]&0xF])
- case r > utf8.MaxRune:
- r = 0xFFFD
- fallthrough
- case r < 0x10000:
- buf = append(buf, `\u`...)
- for s := 12; s >= 0; s -= 4 {
- buf = append(buf, lowerhex[r>>uint(s)&0xF])
- }
- default:
- buf = append(buf, `\U`...)
- for s := 28; s >= 0; s -= 4 {
- buf = append(buf, lowerhex[r>>uint(s)&0xF])
- }
- }
- }
- }
- return buf
-
-}
-
-// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
- username := "-"
- if url.User != nil {
- if name := url.User.Username(); name != "" {
- username = name
- }
- }
-
- host, _, err := net.SplitHostPort(req.RemoteAddr)
-
- if err != nil {
- host = req.RemoteAddr
- }
-
- uri := url.RequestURI()
-
- buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
- buf = append(buf, host...)
- buf = append(buf, " - "...)
- buf = append(buf, username...)
- buf = append(buf, " ["...)
- buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
- buf = append(buf, `] "`...)
- buf = append(buf, req.Method...)
- buf = append(buf, " "...)
- buf = appendQuoted(buf, uri)
- buf = append(buf, " "...)
- buf = append(buf, req.Proto...)
- buf = append(buf, `" `...)
- buf = append(buf, strconv.Itoa(status)...)
- buf = append(buf, " "...)
- buf = append(buf, strconv.Itoa(size)...)
- return buf
-}
-
-// writeLog writes a log entry for req to w in Apache Common Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
- buf := buildCommonLogLine(req, url, ts, status, size)
- buf = append(buf, '\n')
- w.Write(buf)
-}
-
-// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
- buf := buildCommonLogLine(req, url, ts, status, size)
- buf = append(buf, ` "`...)
- buf = appendQuoted(buf, req.Referer())
- buf = append(buf, `" "`...)
- buf = appendQuoted(buf, req.UserAgent())
- buf = append(buf, '"', '\n')
- w.Write(buf)
-}
-
-// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
-// Apache Combined Log Format.
-//
-// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
-//
-// LoggingHandler always sets the ident field of the log to -
-func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
- return combinedLoggingHandler{out, h}
-}
-
-// LoggingHandler return a http.Handler that wraps h and logs requests to out in
-// Apache Common Log Format (CLF).
-//
-// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
-//
-// LoggingHandler always sets the ident field of the log to -
-func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
- return loggingHandler{out, h}
-}
-
-// isContentType validates the Content-Type header
-// is contentType. That is, its type and subtype match.
+// isContentType validates the Content-Type header matches the supplied
+// contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
ct := h.Get("Content-Type")
if i := strings.IndexRune(ct, ';'); i != -1 {
@@ -323,9 +90,9 @@ func isContentType(h http.Header, contentType string) bool {
return ct == contentType
}
-// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
-// is acompatible with the contentTypes list.
-// It writes a HTTP 415 error if that fails.
+// ContentTypeHandler wraps and returns a http.Handler, validating the request
+// content type is compatible with the contentTypes list. It writes a HTTP 415
+// error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
@@ -354,12 +121,14 @@ const (
HTTPMethodOverrideFormKey = "_method"
)
-// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
-// or the _method form key, and overrides (if valid) request.Method with its value.
+// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
+// the X-HTTP-Method-Override header or the _method form key, and overrides (if
+// valid) request.Method with its value.
//
-// This is especially useful for http clients that don't support many http verbs.
-// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
-// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
+// This is especially useful for HTTP clients that don't support many http verbs.
+// It isn't secure to override e.g a GET to a POST, so only POST requests are
+// considered. Likewise, the override method can only be a "write" method: PUT,
+// PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
diff --git a/vendor/github.com/gorilla/handlers/logging.go b/vendor/github.com/gorilla/handlers/logging.go
new file mode 100644
index 000000000..228465eba
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/logging.go
@@ -0,0 +1,244 @@
+// Copyright 2013 The Gorilla 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 handlers
+
+import (
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+ "unicode/utf8"
+
+ "github.com/felixge/httpsnoop"
+)
+
+// Logging
+
+// LogFormatterParams is the structure any formatter will be handed when time to log comes
+type LogFormatterParams struct {
+ Request *http.Request
+ URL url.URL
+ TimeStamp time.Time
+ StatusCode int
+ Size int
+}
+
+// LogFormatter gives the signature of the formatter function passed to CustomLoggingHandler
+type LogFormatter func(writer io.Writer, params LogFormatterParams)
+
+// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
+// friends
+
+type loggingHandler struct {
+ writer io.Writer
+ handler http.Handler
+ formatter LogFormatter
+}
+
+func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ t := time.Now()
+ logger, w := makeLogger(w)
+ url := *req.URL
+
+ h.handler.ServeHTTP(w, req)
+ if req.MultipartForm != nil {
+ req.MultipartForm.RemoveAll()
+ }
+
+ params := LogFormatterParams{
+ Request: req,
+ URL: url,
+ TimeStamp: t,
+ StatusCode: logger.Status(),
+ Size: logger.Size(),
+ }
+
+ h.formatter(h.writer, params)
+}
+
+func makeLogger(w http.ResponseWriter) (*responseLogger, http.ResponseWriter) {
+ logger := &responseLogger{w: w, status: http.StatusOK}
+ return logger, httpsnoop.Wrap(w, httpsnoop.Hooks{
+ Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
+ return logger.Write
+ },
+ WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
+ return logger.WriteHeader
+ },
+ })
+}
+
+const lowerhex = "0123456789abcdef"
+
+func appendQuoted(buf []byte, s string) []byte {
+ var runeTmp [utf8.UTFMax]byte
+ for width := 0; len(s) > 0; s = s[width:] {
+ r := rune(s[0])
+ width = 1
+ if r >= utf8.RuneSelf {
+ r, width = utf8.DecodeRuneInString(s)
+ }
+ if width == 1 && r == utf8.RuneError {
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ continue
+ }
+ if r == rune('"') || r == '\\' { // always backslashed
+ buf = append(buf, '\\')
+ buf = append(buf, byte(r))
+ continue
+ }
+ if strconv.IsPrint(r) {
+ n := utf8.EncodeRune(runeTmp[:], r)
+ buf = append(buf, runeTmp[:n]...)
+ continue
+ }
+ switch r {
+ case '\a':
+ buf = append(buf, `\a`...)
+ case '\b':
+ buf = append(buf, `\b`...)
+ case '\f':
+ buf = append(buf, `\f`...)
+ case '\n':
+ buf = append(buf, `\n`...)
+ case '\r':
+ buf = append(buf, `\r`...)
+ case '\t':
+ buf = append(buf, `\t`...)
+ case '\v':
+ buf = append(buf, `\v`...)
+ default:
+ switch {
+ case r < ' ':
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ case r > utf8.MaxRune:
+ r = 0xFFFD
+ fallthrough
+ case r < 0x10000:
+ buf = append(buf, `\u`...)
+ for s := 12; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ default:
+ buf = append(buf, `\U`...)
+ for s := 28; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ }
+ }
+ }
+ return buf
+}
+
+// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
+ username := "-"
+ if url.User != nil {
+ if name := url.User.Username(); name != "" {
+ username = name
+ }
+ }
+
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+
+ uri := req.RequestURI
+
+ // Requests using the CONNECT method over HTTP/2.0 must use
+ // the authority field (aka r.Host) to identify the target.
+ // Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
+ if req.ProtoMajor == 2 && req.Method == "CONNECT" {
+ uri = req.Host
+ }
+ if uri == "" {
+ uri = url.RequestURI()
+ }
+
+ buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
+ buf = append(buf, host...)
+ buf = append(buf, " - "...)
+ buf = append(buf, username...)
+ buf = append(buf, " ["...)
+ buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
+ buf = append(buf, `] "`...)
+ buf = append(buf, req.Method...)
+ buf = append(buf, " "...)
+ buf = appendQuoted(buf, uri)
+ buf = append(buf, " "...)
+ buf = append(buf, req.Proto...)
+ buf = append(buf, `" `...)
+ buf = append(buf, strconv.Itoa(status)...)
+ buf = append(buf, " "...)
+ buf = append(buf, strconv.Itoa(size)...)
+ return buf
+}
+
+// writeLog writes a log entry for req to w in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeLog(writer io.Writer, params LogFormatterParams) {
+ buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
+ buf = append(buf, '\n')
+ writer.Write(buf)
+}
+
+// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeCombinedLog(writer io.Writer, params LogFormatterParams) {
+ buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
+ buf = append(buf, ` "`...)
+ buf = appendQuoted(buf, params.Request.Referer())
+ buf = append(buf, `" "`...)
+ buf = appendQuoted(buf, params.Request.UserAgent())
+ buf = append(buf, '"', '\n')
+ writer.Write(buf)
+}
+
+// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Combined Log Format.
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return loggingHandler{out, h, writeCombinedLog}
+}
+
+// LoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Common Log Format (CLF).
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+//
+// Example:
+//
+// r := mux.NewRouter()
+// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+// w.Write([]byte("This is a catch-all route"))
+// })
+// loggedRouter := handlers.LoggingHandler(os.Stdout, r)
+// http.ListenAndServe(":1123", loggedRouter)
+//
+func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return loggingHandler{out, h, writeLog}
+}
+
+// CustomLoggingHandler provides a way to supply a custom log formatter
+// while taking advantage of the mechanisms in this package
+func CustomLoggingHandler(out io.Writer, h http.Handler, f LogFormatter) http.Handler {
+ return loggingHandler{out, h, f}
+}
diff --git a/vendor/github.com/gorilla/handlers/proxy_headers.go b/vendor/github.com/gorilla/handlers/proxy_headers.go
index 268de9c6a..ed939dcef 100644
--- a/vendor/github.com/gorilla/handlers/proxy_headers.go
+++ b/vendor/github.com/gorilla/handlers/proxy_headers.go
@@ -8,9 +8,11 @@ import (
var (
// De-facto standard header keys.
- xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
- xRealIP = http.CanonicalHeaderKey("X-Real-IP")
- xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+ xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
+ xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host")
+ xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Proto")
+ xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+ xRealIP = http.CanonicalHeaderKey("X-Real-IP")
)
var (
@@ -28,9 +30,9 @@ var (
// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
-// for the remote (client) IP address, X-Forwarded-Proto for the scheme
-// (http|https) and the RFC7239 Forwarded header, which may include both client
-// IPs and schemes.
+// for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme
+// for the scheme (http|https), X-Forwarded-Host for the host and the RFC7239
+// Forwarded header, which may include both client IPs and schemes.
//
// NOTE: This middleware should only be used when behind a reverse
// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
@@ -49,7 +51,10 @@ func ProxyHeaders(h http.Handler) http.Handler {
if scheme := getScheme(r); scheme != "" {
r.URL.Scheme = scheme
}
-
+ // Set the host with the value passed by the proxy
+ if r.Header.Get(xForwardedHost) != "" {
+ r.Host = r.Header.Get(xForwardedHost)
+ }
// Call the next handler in the chain.
h.ServeHTTP(w, r)
}
@@ -99,7 +104,9 @@ func getScheme(r *http.Request) string {
// Retrieve the scheme from X-Forwarded-Proto.
if proto := r.Header.Get(xForwardedProto); proto != "" {
scheme = strings.ToLower(proto)
- } else if proto := r.Header.Get(forwarded); proto != "" {
+ } else if proto = r.Header.Get(xForwardedScheme); proto != "" {
+ scheme = strings.ToLower(proto)
+ } else if proto = r.Header.Get(forwarded); proto != "" {
// match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be
// the 'proto=' capture, which we ignore. In the case of multiple proto
diff --git a/vendor/github.com/gorilla/handlers/recovery.go b/vendor/github.com/gorilla/handlers/recovery.go
new file mode 100644
index 000000000..4c4c1d9c6
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/recovery.go
@@ -0,0 +1,96 @@
+package handlers
+
+import (
+ "log"
+ "net/http"
+ "runtime/debug"
+)
+
+// RecoveryHandlerLogger is an interface used by the recovering handler to print logs.
+type RecoveryHandlerLogger interface {
+ Println(...interface{})
+}
+
+type recoveryHandler struct {
+ handler http.Handler
+ logger RecoveryHandlerLogger
+ printStack bool
+}
+
+// RecoveryOption provides a functional approach to define
+// configuration for a handler; such as setting the logging
+// whether or not to print stack traces on panic.
+type RecoveryOption func(http.Handler)
+
+func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
+ for _, option := range opts {
+ option(h)
+ }
+
+ return h
+}
+
+// RecoveryHandler is HTTP middleware that recovers from a panic,
+// logs the panic, writes http.StatusInternalServerError, and
+// continues to the next handler.
+//
+// Example:
+//
+// r := mux.NewRouter()
+// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+// panic("Unexpected error!")
+// })
+//
+// http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
+func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
+ return func(h http.Handler) http.Handler {
+ r := &recoveryHandler{handler: h}
+ return parseRecoveryOptions(r, opts...)
+ }
+}
+
+// RecoveryLogger is a functional option to override
+// the default logger
+func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption {
+ return func(h http.Handler) {
+ r := h.(*recoveryHandler)
+ r.logger = logger
+ }
+}
+
+// PrintRecoveryStack is a functional option to enable
+// or disable printing stack traces on panic.
+func PrintRecoveryStack(print bool) RecoveryOption {
+ return func(h http.Handler) {
+ r := h.(*recoveryHandler)
+ r.printStack = print
+ }
+}
+
+func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ defer func() {
+ if err := recover(); err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ h.log(err)
+ }
+ }()
+
+ h.handler.ServeHTTP(w, req)
+}
+
+func (h recoveryHandler) log(v ...interface{}) {
+ if h.logger != nil {
+ h.logger.Println(v...)
+ } else {
+ log.Println(v...)
+ }
+
+ if h.printStack {
+ stack := string(debug.Stack())
+ if h.logger != nil {
+ h.logger.Println(stack)
+ } else {
+ log.Println(stack)
+ }
+ }
+}
diff --git a/vendor/github.com/jinzhu/copier/copier.go b/vendor/github.com/jinzhu/copier/copier.go
index 6d21da869..6dc9600c8 100644
--- a/vendor/github.com/jinzhu/copier/copier.go
+++ b/vendor/github.com/jinzhu/copier/copier.go
@@ -24,6 +24,13 @@ const (
// Denotes that the value as been copied
hasCopied
+
+ // Some default converter types for a nicer syntax
+ String string = ""
+ Bool bool = false
+ Int int = 0
+ Float32 float32 = 0
+ Float64 float64 = 0
)
// Option sets copy options
@@ -32,6 +39,18 @@ type Option struct {
// struct having all it's fields set to their zero values respectively (see IsZero() in reflect/value.go)
IgnoreEmpty bool
DeepCopy bool
+ Converters []TypeConverter
+}
+
+type TypeConverter struct {
+ SrcType interface{}
+ DstType interface{}
+ Fn func(src interface{}) (interface{}, error)
+}
+
+type converterPair struct {
+ SrcType reflect.Type
+ DstType reflect.Type
}
// Tag Flags
@@ -59,12 +78,27 @@ func CopyWithOption(toValue interface{}, fromValue interface{}, opt Option) (err
func copier(toValue interface{}, fromValue interface{}, opt Option) (err error) {
var (
- isSlice bool
- amount = 1
- from = indirect(reflect.ValueOf(fromValue))
- to = indirect(reflect.ValueOf(toValue))
+ isSlice bool
+ amount = 1
+ from = indirect(reflect.ValueOf(fromValue))
+ to = indirect(reflect.ValueOf(toValue))
+ converters map[converterPair]TypeConverter
)
+ // save convertes into map for faster lookup
+ for i := range opt.Converters {
+ if converters == nil {
+ converters = make(map[converterPair]TypeConverter)
+ }
+
+ pair := converterPair{
+ SrcType: reflect.TypeOf(opt.Converters[i].SrcType),
+ DstType: reflect.TypeOf(opt.Converters[i].DstType),
+ }
+
+ converters[pair] = opt.Converters[i]
+ }
+
if !to.CanAddr() {
return ErrInvalidCopyDestination
}
@@ -113,13 +147,16 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
for _, k := range from.MapKeys() {
toKey := indirect(reflect.New(toType.Key()))
- if !set(toKey, k, opt.DeepCopy) {
+ if !set(toKey, k, opt.DeepCopy, converters) {
return fmt.Errorf("%w map, old key: %v, new key: %v", ErrNotSupported, k.Type(), toType.Key())
}
- elemType, _ := indirectType(toType.Elem())
+ elemType := toType.Elem()
+ if elemType.Kind() != reflect.Slice {
+ elemType, _ = indirectType(elemType)
+ }
toValue := indirect(reflect.New(elemType))
- if !set(toValue, from.MapIndex(k), opt.DeepCopy) {
+ if !set(toValue, from.MapIndex(k), opt.DeepCopy, converters) {
if err = copier(toValue.Addr().Interface(), from.MapIndex(k).Interface(), opt); err != nil {
return err
}
@@ -148,7 +185,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
to.Set(reflect.Append(to, reflect.New(to.Type().Elem()).Elem()))
}
- if !set(to.Index(i), from.Index(i), opt.DeepCopy) {
+ if !set(to.Index(i), from.Index(i), opt.DeepCopy, converters) {
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt)
if err != nil {
@@ -203,6 +240,8 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
// check source
if source.IsValid() {
+ copyUnexportedStructFields(dest, source)
+
// Copy from source field to dest field or method
fromTypeFields := deepFields(fromType)
for _, field := range fromTypeFields {
@@ -249,7 +288,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
toField := dest.FieldByName(destFieldName)
if toField.IsValid() {
if toField.CanSet() {
- if !set(toField, fromField, opt.DeepCopy) {
+ if !set(toField, fromField, opt.DeepCopy, converters) {
if err := copier(toField.Addr().Interface(), fromField.Interface(), opt); err != nil {
return err
}
@@ -291,7 +330,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
if toField := dest.FieldByName(destFieldName); toField.IsValid() && toField.CanSet() {
values := fromMethod.Call([]reflect.Value{})
if len(values) >= 1 {
- set(toField, values[0], opt.DeepCopy)
+ set(toField, values[0], opt.DeepCopy, converters)
}
}
}
@@ -303,7 +342,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
if to.Len() < i+1 {
to.Set(reflect.Append(to, dest.Addr()))
} else {
- if !set(to.Index(i), dest.Addr(), opt.DeepCopy) {
+ if !set(to.Index(i), dest.Addr(), opt.DeepCopy, converters) {
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), dest.Addr().Interface(), opt)
if err != nil {
@@ -315,7 +354,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
if to.Len() < i+1 {
to.Set(reflect.Append(to, dest))
} else {
- if !set(to.Index(i), dest, opt.DeepCopy) {
+ if !set(to.Index(i), dest, opt.DeepCopy, converters) {
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), dest.Interface(), opt)
if err != nil {
@@ -334,6 +373,24 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
return
}
+func copyUnexportedStructFields(to, from reflect.Value) {
+ if from.Kind() != reflect.Struct || to.Kind() != reflect.Struct || !from.Type().AssignableTo(to.Type()) {
+ return
+ }
+
+ // create a shallow copy of 'to' to get all fields
+ tmp := indirect(reflect.New(to.Type()))
+ tmp.Set(from)
+
+ // revert exported fields
+ for i := 0; i < to.NumField(); i++ {
+ if tmp.Field(i).CanSet() {
+ tmp.Field(i).Set(to.Field(i))
+ }
+ }
+ to.Set(tmp)
+}
+
func shouldIgnore(v reflect.Value, ignoreEmpty bool) bool {
if !ignoreEmpty {
return false
@@ -352,10 +409,10 @@ func deepFields(reflectType reflect.Type) []reflect.StructField {
// field name. It is empty for upper case (exported) field names.
// See https://golang.org/ref/spec#Uniqueness_of_identifiers
if v.PkgPath == "" {
+ fields = append(fields, v)
if v.Anonymous {
+ // also consider fields of anonymous fields as fields of the root
fields = append(fields, deepFields(v.Type)...)
- } else {
- fields = append(fields, v)
}
}
}
@@ -381,8 +438,14 @@ func indirectType(reflectType reflect.Type) (_ reflect.Type, isPtr bool) {
return reflectType, isPtr
}
-func set(to, from reflect.Value, deepCopy bool) bool {
+func set(to, from reflect.Value, deepCopy bool, converters map[converterPair]TypeConverter) bool {
if from.IsValid() {
+ if ok, err := lookupAndCopyWithConverter(to, from, converters); err != nil {
+ return false
+ } else if ok {
+ return true
+ }
+
if to.Kind() == reflect.Ptr {
// set `to` to nil if from is nil
if from.Kind() == reflect.Ptr && from.IsNil() {
@@ -416,6 +479,9 @@ func set(to, from reflect.Value, deepCopy bool) bool {
toKind = reflect.TypeOf(to.Interface()).Kind()
}
}
+ if from.Kind() == reflect.Ptr && from.IsNil() {
+ return true
+ }
if toKind == reflect.Struct || toKind == reflect.Map || toKind == reflect.Slice {
return false
}
@@ -457,7 +523,7 @@ func set(to, from reflect.Value, deepCopy bool) bool {
to.Set(rv)
}
} else if from.Kind() == reflect.Ptr {
- return set(to, from.Elem(), deepCopy)
+ return set(to, from.Elem(), deepCopy, converters)
} else {
return false
}
@@ -466,6 +532,33 @@ func set(to, from reflect.Value, deepCopy bool) bool {
return true
}
+// lookupAndCopyWithConverter looks up the type pair, on success the TypeConverter Fn func is called to copy src to dst field.
+func lookupAndCopyWithConverter(to, from reflect.Value, converters map[converterPair]TypeConverter) (copied bool, err error) {
+ pair := converterPair{
+ SrcType: from.Type(),
+ DstType: to.Type(),
+ }
+
+ if cnv, ok := converters[pair]; ok {
+ result, err := cnv.Fn(from.Interface())
+
+ if err != nil {
+ return false, err
+ }
+
+ if result != nil {
+ to.Set(reflect.ValueOf(result))
+ } else {
+ // in case we've got a nil value to copy
+ to.Set(reflect.Zero(to.Type()))
+ }
+
+ return true, nil
+ }
+
+ return false, nil
+}
+
// parseTags Parses struct tags and returns uint8 bit flags.
func parseTags(tag string) (flg uint8, name string, err error) {
for _, t := range strings.Split(tag, ",") {
diff --git a/vendor/github.com/klauspost/compress/.goreleaser.yml b/vendor/github.com/klauspost/compress/.goreleaser.yml
index c9014ce1d..0af08e65e 100644
--- a/vendor/github.com/klauspost/compress/.goreleaser.yml
+++ b/vendor/github.com/klauspost/compress/.goreleaser.yml
@@ -3,6 +3,7 @@
before:
hooks:
- ./gen.sh
+ - go install mvdan.cc/garble@latest
builds:
-
@@ -31,6 +32,7 @@ builds:
- mips64le
goarm:
- 7
+ gobinary: garble
-
id: "s2d"
binary: s2d
@@ -57,6 +59,7 @@ builds:
- mips64le
goarm:
- 7
+ gobinary: garble
-
id: "s2sx"
binary: s2sx
@@ -84,6 +87,7 @@ builds:
- mips64le
goarm:
- 7
+ gobinary: garble
archives:
-
diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md
index 3429879eb..e8ff994f8 100644
--- a/vendor/github.com/klauspost/compress/README.md
+++ b/vendor/github.com/klauspost/compress/README.md
@@ -17,6 +17,13 @@ This package provides various compression algorithms.
# changelog
+* Jan 11, 2022 (v1.14.1)
+ * s2: Add stream index in [#462](https://github.com/klauspost/compress/pull/462)
+ * flate: Speed and efficiency improvements in [#439](https://github.com/klauspost/compress/pull/439) [#461](https://github.com/klauspost/compress/pull/461) [#455](https://github.com/klauspost/compress/pull/455) [#452](https://github.com/klauspost/compress/pull/452) [#458](https://github.com/klauspost/compress/pull/458)
+ * zstd: Performance improvement in [#420]( https://github.com/klauspost/compress/pull/420) [#456](https://github.com/klauspost/compress/pull/456) [#437](https://github.com/klauspost/compress/pull/437) [#467](https://github.com/klauspost/compress/pull/467) [#468](https://github.com/klauspost/compress/pull/468)
+ * zstd: add arm64 xxhash assembly in [#464](https://github.com/klauspost/compress/pull/464)
+ * Add garbled for binaries for s2 in [#445](https://github.com/klauspost/compress/pull/445)
+
* Aug 30, 2021 (v1.13.5)
* gz/zlib/flate: Alias stdlib errors [#425](https://github.com/klauspost/compress/pull/425)
* s2: Add block support to commandline tools [#413](https://github.com/klauspost/compress/pull/413)
@@ -432,6 +439,13 @@ For more information see my blog post on [Fast Linear Time Compression](http://b
This is implemented on Go 1.7 as "Huffman Only" mode, though not exposed for gzip.
+# Other packages
+
+Here are other packages of good quality and pure Go (no cgo wrappers or autoconverted code):
+
+* [github.com/pierrec/lz4](https://github.com/pierrec/lz4) - strong multithreaded LZ4 compression.
+* [github.com/cosnicolaou/pbzip2](https://github.com/cosnicolaou/pbzip2) - multithreaded bzip2 decompression.
+* [github.com/dsnet/compress](https://github.com/dsnet/compress) - brotli decompression, bzip2 writer.
# license
diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go
index 5283ac5a5..bffa2f332 100644
--- a/vendor/github.com/klauspost/compress/flate/deflate.go
+++ b/vendor/github.com/klauspost/compress/flate/deflate.go
@@ -6,6 +6,7 @@
package flate
import (
+ "encoding/binary"
"fmt"
"io"
"math"
@@ -37,15 +38,17 @@ const (
maxMatchLength = 258 // The longest match for the compressor
minOffsetSize = 1 // The shortest offset that makes any sense
- // The maximum number of tokens we put into a single flat block, just too
- // stop things from getting too large.
- maxFlateBlockTokens = 1 << 14
+ // The maximum number of tokens we will encode at the time.
+ // Smaller sizes usually creates less optimal blocks.
+ // Bigger can make context switching slow.
+ // We use this for levels 7-9, so we make it big.
+ maxFlateBlockTokens = 1 << 15
maxStoreBlockSize = 65535
hashBits = 17 // After 17 performance degrades
hashSize = 1 << hashBits
hashMask = (1 << hashBits) - 1
hashShift = (hashBits + minMatchLength - 1) / minMatchLength
- maxHashOffset = 1 << 24
+ maxHashOffset = 1 << 28
skipNever = math.MaxInt32
@@ -70,9 +73,9 @@ var levels = []compressionLevel{
{0, 0, 0, 0, 0, 6},
// Levels 7-9 use increasingly more lazy matching
// and increasingly stringent conditions for "good enough".
- {8, 8, 24, 16, skipNever, 7},
- {10, 16, 24, 64, skipNever, 8},
- {32, 258, 258, 4096, skipNever, 9},
+ {8, 12, 16, 24, skipNever, 7},
+ {16, 30, 40, 64, skipNever, 8},
+ {32, 258, 258, 1024, skipNever, 9},
}
// advancedState contains state for the advanced levels, with bigger hash tables, etc.
@@ -93,8 +96,9 @@ type advancedState struct {
hashOffset int
// input window: unprocessed data is window[index:windowEnd]
- index int
- hashMatch [maxMatchLength + minMatchLength]uint32
+ index int
+ estBitsPerByte int
+ hashMatch [maxMatchLength + minMatchLength]uint32
hash uint32
ii uint16 // position of last match, intended to overflow to reset.
@@ -103,6 +107,7 @@ type advancedState struct {
type compressor struct {
compressionLevel
+ h *huffmanEncoder
w *huffmanBitWriter
// compression algorithm
@@ -170,7 +175,8 @@ func (d *compressor) writeBlock(tok *tokens, index int, eof bool) error {
window = d.window[d.blockStart:index]
}
d.blockStart = index
- d.w.writeBlock(tok, eof, window)
+ //d.w.writeBlock(tok, eof, window)
+ d.w.writeBlockDynamic(tok, eof, window, d.sync)
return d.w.err
}
return nil
@@ -263,7 +269,7 @@ func (d *compressor) fillWindow(b []byte) {
// Try to find a match starting at index whose length is greater than prevSize.
// We only look at chainCount possibilities before giving up.
// pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead
-func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
+func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, offset int, ok bool) {
minMatchLook := maxMatchLength
if lookahead < minMatchLook {
minMatchLook = lookahead
@@ -279,36 +285,75 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
// If we've got a match that's good enough, only look in 1/4 the chain.
tries := d.chain
- length = prevLength
- if length >= d.good {
- tries >>= 2
- }
+ length = minMatchLength - 1
wEnd := win[pos+length]
wPos := win[pos:]
minIndex := pos - windowSize
+ if minIndex < 0 {
+ minIndex = 0
+ }
+ offset = 0
+
+ cGain := 0
+ if d.chain < 100 {
+ for i := prevHead; tries > 0; tries-- {
+ if wEnd == win[i+length] {
+ n := matchLen(win[i:i+minMatchLook], wPos)
+ if n > length {
+ length = n
+ offset = pos - i
+ ok = true
+ if n >= nice {
+ // The match is good enough that we don't try to find a better one.
+ break
+ }
+ wEnd = win[pos+n]
+ }
+ }
+ if i <= minIndex {
+ // hashPrev[i & windowMask] has already been overwritten, so stop now.
+ break
+ }
+ i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset
+ if i < minIndex {
+ break
+ }
+ }
+ return
+ }
+ // Some like it higher (CSV), some like it lower (JSON)
+ const baseCost = 6
+ // Base is 4 bytes at with an additional cost.
+ // Matches must be better than this.
for i := prevHead; tries > 0; tries-- {
if wEnd == win[i+length] {
n := matchLen(win[i:i+minMatchLook], wPos)
-
- if n > length && (n > minMatchLength || pos-i <= 4096) {
- length = n
- offset = pos - i
- ok = true
- if n >= nice {
- // The match is good enough that we don't try to find a better one.
- break
+ if n > length {
+ // Calculate gain. Estimate
+ newGain := d.h.bitLengthRaw(wPos[:n]) - int(offsetExtraBits[offsetCode(uint32(pos-i))]) - baseCost - int(lengthExtraBits[lengthCodes[(n-3)&255]])
+
+ //fmt.Println(n, "gain:", newGain, "prev:", cGain, "raw:", d.h.bitLengthRaw(wPos[:n]))
+ if newGain > cGain {
+ length = n
+ offset = pos - i
+ cGain = newGain
+ ok = true
+ if n >= nice {
+ // The match is good enough that we don't try to find a better one.
+ break
+ }
+ wEnd = win[pos+n]
}
- wEnd = win[pos+n]
}
}
- if i == minIndex {
+ if i <= minIndex {
// hashPrev[i & windowMask] has already been overwritten, so stop now.
break
}
i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset
- if i < minIndex || i < 0 {
+ if i < minIndex {
break
}
}
@@ -327,8 +372,7 @@ func (d *compressor) writeStoredBlock(buf []byte) error {
// of the supplied slice.
// The caller must ensure that len(b) >= 4.
func hash4(b []byte) uint32 {
- b = b[:4]
- return hash4u(uint32(b[3])|uint32(b[2])<<8|uint32(b[1])<<16|uint32(b[0])<<24, hashBits)
+ return hash4u(binary.LittleEndian.Uint32(b), hashBits)
}
// bulkHash4 will compute hashes using the same
@@ -337,11 +381,12 @@ func bulkHash4(b []byte, dst []uint32) {
if len(b) < 4 {
return
}
- hb := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+ hb := binary.LittleEndian.Uint32(b)
+
dst[0] = hash4u(hb, hashBits)
end := len(b) - 4 + 1
for i := 1; i < end; i++ {
- hb = (hb << 8) | uint32(b[i+3])
+ hb = (hb >> 8) | uint32(b[i+3])<<24
dst[i] = hash4u(hb, hashBits)
}
}
@@ -374,10 +419,21 @@ func (d *compressor) deflateLazy() {
if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync {
return
}
+ if d.windowEnd != s.index && d.chain > 100 {
+ // Get literal huffman coder.
+ if d.h == nil {
+ d.h = newHuffmanEncoder(maxFlateBlockTokens)
+ }
+ var tmp [256]uint16
+ for _, v := range d.window[s.index:d.windowEnd] {
+ tmp[v]++
+ }
+ d.h.generate(tmp[:], 15)
+ }
s.maxInsertIndex = d.windowEnd - (minMatchLength - 1)
if s.index < s.maxInsertIndex {
- s.hash = hash4(d.window[s.index : s.index+minMatchLength])
+ s.hash = hash4(d.window[s.index:])
}
for {
@@ -410,7 +466,7 @@ func (d *compressor) deflateLazy() {
}
if s.index < s.maxInsertIndex {
// Update the hash
- s.hash = hash4(d.window[s.index : s.index+minMatchLength])
+ s.hash = hash4(d.window[s.index:])
ch := s.hashHead[s.hash&hashMask]
s.chainHead = int(ch)
s.hashPrev[s.index&windowMask] = ch
@@ -426,12 +482,37 @@ func (d *compressor) deflateLazy() {
}
if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy {
- if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok {
+ if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, lookahead); ok {
s.length = newLength
s.offset = newOffset
}
}
+
if prevLength >= minMatchLength && s.length <= prevLength {
+ // Check for better match at end...
+ //
+ // checkOff must be >=2 since we otherwise risk checking s.index
+ // Offset of 2 seems to yield best results.
+ const checkOff = 2
+ prevIndex := s.index - 1
+ if prevIndex+prevLength+checkOff < s.maxInsertIndex {
+ end := lookahead
+ if lookahead > maxMatchLength {
+ end = maxMatchLength
+ }
+ end += prevIndex
+ idx := prevIndex + prevLength - (4 - checkOff)
+ h := hash4(d.window[idx:])
+ ch2 := int(s.hashHead[h&hashMask]) - s.hashOffset - prevLength + (4 - checkOff)
+ if ch2 > minIndex {
+ length := matchLen(d.window[prevIndex:end], d.window[ch2:])
+ // It seems like a pure length metric is best.
+ if length > prevLength {
+ prevLength = length
+ prevOffset = prevIndex - ch2
+ }
+ }
+ }
// There was a match at the previous step, and the current match is
// not better. Output the previous match.
d.tokens.AddMatch(uint32(prevLength-3), uint32(prevOffset-minOffsetSize))
@@ -479,6 +560,7 @@ func (d *compressor) deflateLazy() {
}
d.tokens.Reset()
}
+ s.ii = 0
} else {
// Reset, if we got a match this run.
if s.length >= minMatchLength {
@@ -498,13 +580,12 @@ func (d *compressor) deflateLazy() {
// If we have a long run of no matches, skip additional bytes
// Resets when s.ii overflows after 64KB.
- if s.ii > 31 {
- n := int(s.ii >> 5)
+ if n := int(s.ii) - d.chain; n > 0 {
+ n = 1 + int(n>>6)
for j := 0; j < n; j++ {
if s.index >= d.windowEnd-1 {
break
}
-
d.tokens.AddLiteral(d.window[s.index-1])
if d.tokens.n == maxFlateBlockTokens {
if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil {
@@ -512,6 +593,14 @@ func (d *compressor) deflateLazy() {
}
d.tokens.Reset()
}
+ // Index...
+ if s.index < s.maxInsertIndex {
+ h := hash4(d.window[s.index:])
+ ch := s.hashHead[h]
+ s.chainHead = int(ch)
+ s.hashPrev[s.index&windowMask] = ch
+ s.hashHead[h] = uint32(s.index + s.hashOffset)
+ }
s.index++
}
// Flush last byte
@@ -611,7 +700,9 @@ func (d *compressor) write(b []byte) (n int, err error) {
}
n = len(b)
for len(b) > 0 {
- d.step(d)
+ if d.windowEnd == len(d.window) || d.sync {
+ d.step(d)
+ }
b = b[d.fill(d, b):]
if d.err != nil {
return 0, d.err
@@ -652,13 +743,13 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
level = 5
fallthrough
case level >= 1 && level <= 6:
- d.w.logNewTablePenalty = 8
+ d.w.logNewTablePenalty = 7
d.fast = newFastEnc(level)
d.window = make([]byte, maxStoreBlockSize)
d.fill = (*compressor).fillBlock
d.step = (*compressor).storeFast
case 7 <= level && level <= 9:
- d.w.logNewTablePenalty = 10
+ d.w.logNewTablePenalty = 8
d.state = &advancedState{}
d.compressionLevel = levels[level]
d.initDeflate()
diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
index a746eb733..0b2e54972 100644
--- a/vendor/github.com/klauspost/compress/flate/fast_encoder.go
+++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
@@ -213,11 +213,9 @@ func (e *fastGen) Reset() {
// matchLen returns the maximum length.
// 'a' must be the shortest of the two.
func matchLen(a, b []byte) int {
- b = b[:len(a)]
var checked int
for len(a) >= 8 {
- b = b[:len(a)]
if diff := binary.LittleEndian.Uint64(a) ^ binary.LittleEndian.Uint64(b); diff != 0 {
return checked + (bits.TrailingZeros64(diff) >> 3)
}
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 3ad5e9807..fd49efd75 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go
@@ -52,18 +52,18 @@ var lengthBase = [32]uint8{
}
// offset code word extra bits.
-var offsetExtraBits = [64]int8{
+var offsetExtraBits = [32]int8{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
/* extended window */
- 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20,
+ 14, 14,
}
var offsetCombined = [32]uint32{}
func init() {
- var offsetBase = [64]uint32{
+ var offsetBase = [32]uint32{
/* normal deflate */
0x000000, 0x000001, 0x000002, 0x000003, 0x000004,
0x000006, 0x000008, 0x00000c, 0x000010, 0x000018,
@@ -73,9 +73,7 @@ func init() {
0x001800, 0x002000, 0x003000, 0x004000, 0x006000,
/* extended window */
- 0x008000, 0x00c000, 0x010000, 0x018000, 0x020000,
- 0x030000, 0x040000, 0x060000, 0x080000, 0x0c0000,
- 0x100000, 0x180000, 0x200000, 0x300000,
+ 0x008000, 0x00c000,
}
for i := range offsetCombined[:] {
@@ -155,37 +153,33 @@ func (w *huffmanBitWriter) reset(writer io.Writer) {
w.lastHuffMan = false
}
-func (w *huffmanBitWriter) canReuse(t *tokens) (offsets, lits bool) {
- offsets, lits = true, true
+func (w *huffmanBitWriter) canReuse(t *tokens) (ok bool) {
a := t.offHist[:offsetCodeCount]
- b := w.offsetFreq[:len(a)]
- for i := range a {
- if b[i] == 0 && a[i] != 0 {
- offsets = false
- break
+ b := w.offsetEncoding.codes
+ b = b[:len(a)]
+ for i, v := range a {
+ if v != 0 && b[i].len == 0 {
+ return false
}
}
a = t.extraHist[:literalCount-256]
- b = w.literalFreq[256:literalCount]
+ b = w.literalEncoding.codes[256:literalCount]
b = b[:len(a)]
- for i := range a {
- if b[i] == 0 && a[i] != 0 {
- lits = false
- break
+ for i, v := range a {
+ if v != 0 && b[i].len == 0 {
+ return false
}
}
- if lits {
- a = t.litHist[:]
- b = w.literalFreq[:len(a)]
- for i := range a {
- if b[i] == 0 && a[i] != 0 {
- lits = false
- break
- }
+
+ a = t.litHist[:256]
+ b = w.literalEncoding.codes[:len(a)]
+ for i, v := range a {
+ if v != 0 && b[i].len == 0 {
+ return false
}
}
- return
+ return true
}
func (w *huffmanBitWriter) flush() {
@@ -222,7 +216,7 @@ func (w *huffmanBitWriter) write(b []byte) {
}
func (w *huffmanBitWriter) writeBits(b int32, nb uint16) {
- w.bits |= uint64(b) << w.nbits
+ w.bits |= uint64(b) << (w.nbits & 63)
w.nbits += nb
if w.nbits >= 48 {
w.writeOutBits()
@@ -423,7 +417,7 @@ func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) {
func (w *huffmanBitWriter) writeCode(c hcode) {
// The function does not get inlined if we "& 63" the shift.
- w.bits |= uint64(c.code) << w.nbits
+ w.bits |= uint64(c.code) << (w.nbits & 63)
w.nbits += c.len
if w.nbits >= 48 {
w.writeOutBits()
@@ -566,7 +560,7 @@ func (w *huffmanBitWriter) writeBlock(tokens *tokens, eof bool, input []byte) {
w.lastHeader = 0
}
numLiterals, numOffsets := w.indexTokens(tokens, false)
- w.generate(tokens)
+ w.generate()
var extraBits int
storedSize, storable := w.storedSize(input)
if storable {
@@ -595,7 +589,7 @@ func (w *huffmanBitWriter) writeBlock(tokens *tokens, eof bool, input []byte) {
}
// Stored bytes?
- if storable && storedSize < size {
+ if storable && storedSize <= size {
w.writeStoredHeader(len(input), eof)
w.writeBytes(input)
return
@@ -634,22 +628,39 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b
w.lastHeader = 0
w.lastHuffMan = false
}
- if !sync {
- tokens.Fill()
+
+ // fillReuse enables filling of empty values.
+ // This will make encodings always reusable without testing.
+ // However, this does not appear to benefit on most cases.
+ const fillReuse = false
+
+ // Check if we can reuse...
+ if !fillReuse && w.lastHeader > 0 && !w.canReuse(tokens) {
+ w.writeCode(w.literalEncoding.codes[endBlockMarker])
+ w.lastHeader = 0
}
+
numLiterals, numOffsets := w.indexTokens(tokens, !sync)
+ extraBits := 0
+ ssize, storable := w.storedSize(input)
+
+ const usePrefs = true
+ if storable || w.lastHeader > 0 {
+ extraBits = w.extraBitSize()
+ }
var size int
+
// Check if we should reuse.
if w.lastHeader > 0 {
// Estimate size for using a new table.
// Use the previous header size as the best estimate.
newSize := w.lastHeader + tokens.EstimatedBits()
- newSize += newSize >> w.logNewTablePenalty
+ newSize += int(w.literalEncoding.codes[endBlockMarker].len) + newSize>>w.logNewTablePenalty
// The estimated size is calculated as an optimal table.
// We add a penalty to make it more realistic and re-use a bit more.
- reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + w.extraBitSize()
+ reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + extraBits
// Check if a new table is better.
if newSize < reuseSize {
@@ -660,35 +671,79 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b
} else {
size = reuseSize
}
+
+ if preSize := w.fixedSize(extraBits) + 7; usePrefs && preSize < size {
+ // Check if we get a reasonable size decrease.
+ if storable && ssize <= size {
+ w.writeStoredHeader(len(input), eof)
+ w.writeBytes(input)
+ return
+ }
+ w.writeFixedHeader(eof)
+ if !sync {
+ tokens.AddEOB()
+ }
+ w.writeTokens(tokens.Slice(), fixedLiteralEncoding.codes, fixedOffsetEncoding.codes)
+ return
+ }
// Check if we get a reasonable size decrease.
- if ssize, storable := w.storedSize(input); storable && ssize < (size+size>>4) {
+ if storable && ssize <= size {
w.writeStoredHeader(len(input), eof)
w.writeBytes(input)
- w.lastHeader = 0
return
}
}
// We want a new block/table
if w.lastHeader == 0 {
- w.generate(tokens)
+ if fillReuse && !sync {
+ w.fillTokens()
+ numLiterals, numOffsets = maxNumLit, maxNumDist
+ } else {
+ w.literalFreq[endBlockMarker] = 1
+ }
+
+ w.generate()
// Generate codegen and codegenFrequencies, which indicates how to encode
// the literalEncoding and the offsetEncoding.
w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding)
w.codegenEncoding.generate(w.codegenFreq[:], 7)
+
var numCodegens int
- size, numCodegens = w.dynamicSize(w.literalEncoding, w.offsetEncoding, w.extraBitSize())
- // Store bytes, if we don't get a reasonable improvement.
- if ssize, storable := w.storedSize(input); storable && ssize < (size+size>>4) {
+ if fillReuse && !sync {
+ // Reindex for accurate size...
+ w.indexTokens(tokens, true)
+ }
+ size, numCodegens = w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits)
+
+ // Store predefined, if we don't get a reasonable improvement.
+ if preSize := w.fixedSize(extraBits); usePrefs && preSize <= size {
+ // Store bytes, if we don't get an improvement.
+ if storable && ssize <= preSize {
+ w.writeStoredHeader(len(input), eof)
+ w.writeBytes(input)
+ return
+ }
+ w.writeFixedHeader(eof)
+ if !sync {
+ tokens.AddEOB()
+ }
+ w.writeTokens(tokens.Slice(), fixedLiteralEncoding.codes, fixedOffsetEncoding.codes)
+ return
+ }
+
+ if storable && ssize <= size {
+ // Store bytes, if we don't get an improvement.
w.writeStoredHeader(len(input), eof)
w.writeBytes(input)
- w.lastHeader = 0
return
}
// Write Huffman table.
w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof)
- w.lastHeader, _ = w.headerSize()
+ if !sync {
+ w.lastHeader, _ = w.headerSize()
+ }
w.lastHuffMan = false
}
@@ -699,6 +754,19 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []b
w.writeTokens(tokens.Slice(), w.literalEncoding.codes, w.offsetEncoding.codes)
}
+func (w *huffmanBitWriter) fillTokens() {
+ for i, v := range w.literalFreq[:literalCount] {
+ if v == 0 {
+ w.literalFreq[i] = 1
+ }
+ }
+ for i, v := range w.offsetFreq[:offsetCodeCount] {
+ if v == 0 {
+ w.offsetFreq[i] = 1
+ }
+ }
+}
+
// indexTokens indexes a slice of tokens, and updates
// literalFreq and offsetFreq, and generates literalEncoding
// and offsetEncoding.
@@ -733,7 +801,7 @@ func (w *huffmanBitWriter) indexTokens(t *tokens, filled bool) (numLiterals, num
return
}
-func (w *huffmanBitWriter) generate(t *tokens) {
+func (w *huffmanBitWriter) generate() {
w.literalEncoding.generate(w.literalFreq[:literalCount], 15)
w.offsetEncoding.generate(w.offsetFreq[:offsetCodeCount], 15)
}
@@ -768,7 +836,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
if t < matchType {
//w.writeCode(lits[t.literal()])
c := lits[t.literal()]
- bits |= uint64(c.code) << nbits
+ bits |= uint64(c.code) << (nbits & 63)
nbits += c.len
if nbits >= 48 {
binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
@@ -796,7 +864,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
} else {
// inlined
c := lengths[lengthCode&31]
- bits |= uint64(c.code) << nbits
+ bits |= uint64(c.code) << (nbits & 63)
nbits += c.len
if nbits >= 48 {
binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
@@ -819,7 +887,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
if extraLengthBits > 0 {
//w.writeBits(extraLength, extraLengthBits)
extraLength := int32(length - lengthBase[lengthCode&31])
- bits |= uint64(extraLength) << nbits
+ bits |= uint64(extraLength) << (nbits & 63)
nbits += extraLengthBits
if nbits >= 48 {
binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
@@ -846,7 +914,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
} else {
// inlined
c := offs[offsetCode]
- bits |= uint64(c.code) << nbits
+ bits |= uint64(c.code) << (nbits & 63)
nbits += c.len
if nbits >= 48 {
binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
@@ -867,7 +935,7 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode)
offsetComb := offsetCombined[offsetCode]
if offsetComb > 1<<16 {
//w.writeBits(extraOffset, extraOffsetBits)
- bits |= uint64(offset&matchOffsetOnlyMask-(offsetComb&0xffff)) << nbits
+ bits |= uint64(offset-(offsetComb&0xffff)) << (nbits & 63)
nbits += uint16(offsetComb >> 16)
if nbits >= 48 {
binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
@@ -996,10 +1064,41 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) {
encoding := w.literalEncoding.codes[:256]
// Go 1.16 LOVES having these on stack. At least 1.5x the speed.
bits, nbits, nbytes := w.bits, w.nbits, w.nbytes
+
+ // Unroll, write 3 codes/loop.
+ // Fastest number of unrolls.
+ for len(input) > 3 {
+ // We must have at least 48 bits free.
+ if nbits >= 8 {
+ n := nbits >> 3
+ binary.LittleEndian.PutUint64(w.bytes[nbytes:], bits)
+ bits >>= (n * 8) & 63
+ nbits -= n * 8
+ nbytes += uint8(n)
+ }
+ if nbytes >= bufferFlushSize {
+ if w.err != nil {
+ nbytes = 0
+ return
+ }
+ _, w.err = w.writer.Write(w.bytes[:nbytes])
+ nbytes = 0
+ }
+ a, b := encoding[input[0]], encoding[input[1]]
+ bits |= uint64(a.code) << (nbits & 63)
+ bits |= uint64(b.code) << ((nbits + a.len) & 63)
+ c := encoding[input[2]]
+ nbits += b.len + a.len
+ bits |= uint64(c.code) << (nbits & 63)
+ nbits += c.len
+ input = input[3:]
+ }
+
+ // Remaining...
for _, t := range input {
// Bitwriting inlined, ~30% speedup
c := encoding[t]
- bits |= uint64(c.code) << nbits
+ bits |= uint64(c.code) << (nbits & 63)
nbits += c.len
if debugDeflate {
count += int(c.len)
diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go
index 67b2b3872..f35e00261 100644
--- a/vendor/github.com/klauspost/compress/flate/huffman_code.go
+++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go
@@ -129,9 +129,7 @@ func (h *huffmanEncoder) bitLength(freq []uint16) int {
func (h *huffmanEncoder) bitLengthRaw(b []byte) int {
var total int
for _, f := range b {
- if f != 0 {
- total += int(h.codes[f].len)
- }
+ total += int(h.codes[f].len)
}
return total
}
diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go
index d1edb356c..d5f62f6a2 100644
--- a/vendor/github.com/klauspost/compress/flate/inflate.go
+++ b/vendor/github.com/klauspost/compress/flate/inflate.go
@@ -328,11 +328,17 @@ func (f *decompressor) nextBlock() {
switch typ {
case 0:
f.dataBlock()
+ if debugDecode {
+ fmt.Println("stored block")
+ }
case 1:
// compressed, fixed Huffman tables
f.hl = &fixedHuffmanDecoder
f.hd = nil
f.huffmanBlockDecoder()()
+ if debugDecode {
+ fmt.Println("predefinied huffman block")
+ }
case 2:
// compressed, dynamic Huffman tables
if f.err = f.readHuffman(); f.err != nil {
@@ -341,6 +347,9 @@ func (f *decompressor) nextBlock() {
f.hl = &f.h1
f.hd = &f.h2
f.huffmanBlockDecoder()()
+ if debugDecode {
+ fmt.Println("dynamic huffman block")
+ }
default:
// 3 is reserved.
if debugDecode {
diff --git a/vendor/github.com/klauspost/compress/flate/token.go b/vendor/github.com/klauspost/compress/flate/token.go
index eb862d7a9..3a9618ee1 100644
--- a/vendor/github.com/klauspost/compress/flate/token.go
+++ b/vendor/github.com/klauspost/compress/flate/token.go
@@ -129,11 +129,11 @@ var offsetCodes14 = [256]uint32{
type token uint32
type tokens struct {
- nLits int
extraHist [32]uint16 // codes 256->maxnumlit
offHist [32]uint16 // offset codes
litHist [256]uint16 // codes 0->255
- n uint16 // Must be able to contain maxStoreBlockSize
+ nFilled int
+ n uint16 // Must be able to contain maxStoreBlockSize
tokens [maxStoreBlockSize + 1]token
}
@@ -142,7 +142,7 @@ func (t *tokens) Reset() {
return
}
t.n = 0
- t.nLits = 0
+ t.nFilled = 0
for i := range t.litHist[:] {
t.litHist[i] = 0
}
@@ -161,12 +161,12 @@ func (t *tokens) Fill() {
for i, v := range t.litHist[:] {
if v == 0 {
t.litHist[i] = 1
- t.nLits++
+ t.nFilled++
}
}
for i, v := range t.extraHist[:literalCount-256] {
if v == 0 {
- t.nLits++
+ t.nFilled++
t.extraHist[i] = 1
}
}
@@ -202,14 +202,12 @@ func emitLiteral(dst *tokens, lit []byte) {
dst.litHist[v]++
}
dst.n += uint16(len(lit))
- dst.nLits += len(lit)
}
func (t *tokens) AddLiteral(lit byte) {
t.tokens[t.n] = token(lit)
t.litHist[lit]++
t.n++
- t.nLits++
}
// from https://stackoverflow.com/a/28730362
@@ -230,8 +228,9 @@ func (t *tokens) EstimatedBits() int {
shannon := float32(0)
bits := int(0)
nMatches := 0
- if t.nLits > 0 {
- invTotal := 1.0 / float32(t.nLits)
+ total := int(t.n) + t.nFilled
+ if total > 0 {
+ invTotal := 1.0 / float32(total)
for _, v := range t.litHist[:] {
if v > 0 {
n := float32(v)
@@ -275,7 +274,6 @@ func (t *tokens) AddMatch(xlength uint32, xoffset uint32) {
}
oCode := offsetCode(xoffset)
xoffset |= oCode << 16
- t.nLits++
t.extraHist[lengthCodes1[uint8(xlength)]]++
t.offHist[oCode]++
@@ -301,7 +299,6 @@ func (t *tokens) AddMatchLong(xlength int32, xoffset uint32) {
}
xlength -= xl
xl -= baseMatchLength
- t.nLits++
t.extraHist[lengthCodes1[uint8(xl)]]++
t.offHist[oc]++
t.tokens[t.n] = token(matchType | uint32(xl)<<lengthShift | xoffset)
diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go
index 9b7cc8e97..2a06bd1a7 100644
--- a/vendor/github.com/klauspost/compress/huff0/decompress.go
+++ b/vendor/github.com/klauspost/compress/huff0/decompress.go
@@ -20,7 +20,7 @@ type dEntrySingle struct {
// double-symbols decoding
type dEntryDouble struct {
- seq uint16
+ seq [4]byte
nBits uint8
len uint8
}
@@ -753,23 +753,21 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
br[stream2].fillFast()
val := br[stream].peekBitsFast(d.actualTableLog)
- v := single[val&tlMask]
- br[stream].advance(uint8(v.entry))
- buf[off+bufoff*stream] = uint8(v.entry >> 8)
-
val2 := br[stream2].peekBitsFast(d.actualTableLog)
+ v := single[val&tlMask]
v2 := single[val2&tlMask]
+ br[stream].advance(uint8(v.entry))
br[stream2].advance(uint8(v2.entry))
+ buf[off+bufoff*stream] = uint8(v.entry >> 8)
buf[off+bufoff*stream2] = uint8(v2.entry >> 8)
val = br[stream].peekBitsFast(d.actualTableLog)
- v = single[val&tlMask]
- br[stream].advance(uint8(v.entry))
- buf[off+bufoff*stream+1] = uint8(v.entry >> 8)
-
val2 = br[stream2].peekBitsFast(d.actualTableLog)
+ v = single[val&tlMask]
v2 = single[val2&tlMask]
+ br[stream].advance(uint8(v.entry))
br[stream2].advance(uint8(v2.entry))
+ buf[off+bufoff*stream+1] = uint8(v.entry >> 8)
buf[off+bufoff*stream2+1] = uint8(v2.entry >> 8)
}
@@ -780,23 +778,21 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
br[stream2].fillFast()
val := br[stream].peekBitsFast(d.actualTableLog)
- v := single[val&tlMask]
- br[stream].advance(uint8(v.entry))
- buf[off+bufoff*stream] = uint8(v.entry >> 8)
-
val2 := br[stream2].peekBitsFast(d.actualTableLog)
+ v := single[val&tlMask]
v2 := single[val2&tlMask]
+ br[stream].advance(uint8(v.entry))
br[stream2].advance(uint8(v2.entry))
+ buf[off+bufoff*stream] = uint8(v.entry >> 8)
buf[off+bufoff*stream2] = uint8(v2.entry >> 8)
val = br[stream].peekBitsFast(d.actualTableLog)
- v = single[val&tlMask]
- br[stream].advance(uint8(v.entry))
- buf[off+bufoff*stream+1] = uint8(v.entry >> 8)
-
val2 = br[stream2].peekBitsFast(d.actualTableLog)
+ v = single[val&tlMask]
v2 = single[val2&tlMask]
+ br[stream].advance(uint8(v.entry))
br[stream2].advance(uint8(v2.entry))
+ buf[off+bufoff*stream+1] = uint8(v.entry >> 8)
buf[off+bufoff*stream2+1] = uint8(v2.entry >> 8)
}
@@ -914,7 +910,7 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
out := dst
dstEvery := (dstSize + 3) / 4
- shift := (8 - d.actualTableLog) & 7
+ shift := (56 + (8 - d.actualTableLog)) & 63
const tlSize = 1 << 8
single := d.dt.single[:tlSize]
@@ -935,79 +931,91 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
// Interleave 2 decodes.
const stream = 0
const stream2 = 1
- br[stream].fillFast()
- br[stream2].fillFast()
-
- v := single[br[stream].peekByteFast()>>shift].entry
+ br1 := &br[stream]
+ br2 := &br[stream2]
+ br1.fillFast()
+ br2.fillFast()
+
+ v := single[uint8(br1.value>>shift)].entry
+ v2 := single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 := single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream+1] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+1] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream+2] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
- buf[off+bufoff*stream+3] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream2+3] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
+ buf[off+bufoff*stream+3] = uint8(v >> 8)
}
{
const stream = 2
const stream2 = 3
- br[stream].fillFast()
- br[stream2].fillFast()
-
- v := single[br[stream].peekByteFast()>>shift].entry
+ br1 := &br[stream]
+ br2 := &br[stream2]
+ br1.fillFast()
+ br2.fillFast()
+
+ v := single[uint8(br1.value>>shift)].entry
+ v2 := single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 := single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream+1] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+1] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream+2] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
-
- v = single[br[stream].peekByteFast()>>shift].entry
- buf[off+bufoff*stream+3] = uint8(v >> 8)
- br[stream].advance(uint8(v))
- v2 = single[br[stream2].peekByteFast()>>shift].entry
+ v = single[uint8(br1.value>>shift)].entry
+ v2 = single[uint8(br2.value>>shift)].entry
+ br1.bitsRead += uint8(v)
+ br1.value <<= v & 63
+ br2.bitsRead += uint8(v2)
+ br2.value <<= v2 & 63
buf[off+bufoff*stream2+3] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
+ buf[off+bufoff*stream+3] = uint8(v >> 8)
}
off += 4
@@ -1073,7 +1081,7 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
}
// Read value and increment offset.
- v := single[br.peekByteFast()>>shift].entry
+ v := single[uint8(br.value>>shift)].entry
nBits := uint8(v)
br.advance(nBits)
bitsLeft -= int(nBits)
@@ -1121,7 +1129,7 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
out := dst
dstEvery := (dstSize + 3) / 4
- const shift = 0
+ const shift = 56
const tlSize = 1 << 8
const tlMask = tlSize - 1
single := d.dt.single[:tlSize]
@@ -1145,37 +1153,41 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
br[stream].fillFast()
br[stream2].fillFast()
- v := single[br[stream].peekByteFast()>>shift].entry
+ v := single[uint8(br[stream].value>>shift)].entry
+ v2 := single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 := single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+1] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+1] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+2] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+3] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+3] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
}
{
@@ -1184,37 +1196,41 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
br[stream].fillFast()
br[stream2].fillFast()
- v := single[br[stream].peekByteFast()>>shift].entry
+ v := single[uint8(br[stream].value>>shift)].entry
+ v2 := single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 := single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+1] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+1] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+2] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+2] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
- v = single[br[stream].peekByteFast()>>shift].entry
+ v = single[uint8(br[stream].value>>shift)].entry
+ v2 = single[uint8(br[stream2].value>>shift)].entry
+ br[stream].bitsRead += uint8(v)
+ br[stream].value <<= v & 63
+ br[stream2].bitsRead += uint8(v2)
+ br[stream2].value <<= v2 & 63
buf[off+bufoff*stream+3] = uint8(v >> 8)
- br[stream].advance(uint8(v))
-
- v2 = single[br[stream2].peekByteFast()>>shift].entry
buf[off+bufoff*stream2+3] = uint8(v2 >> 8)
- br[stream2].advance(uint8(v2))
}
off += 4
@@ -1280,7 +1296,7 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
}
// Read value and increment offset.
- v := single[br.peekByteFast()>>shift].entry
+ v := single[br.peekByteFast()].entry
nBits := uint8(v)
br.advance(nBits)
bitsLeft -= int(nBits)
diff --git a/vendor/github.com/klauspost/compress/zstd/bitreader.go b/vendor/github.com/klauspost/compress/zstd/bitreader.go
index 854458537..753d17df6 100644
--- a/vendor/github.com/klauspost/compress/zstd/bitreader.go
+++ b/vendor/github.com/klauspost/compress/zstd/bitreader.go
@@ -50,16 +50,23 @@ func (b *bitReader) getBits(n uint8) int {
if n == 0 /*|| b.bitsRead >= 64 */ {
return 0
}
- return b.getBitsFast(n)
+ return int(b.get32BitsFast(n))
}
-// getBitsFast requires that at least one bit is requested every time.
+// get32BitsFast requires that at least one bit is requested every time.
// There are no checks if the buffer is filled.
-func (b *bitReader) getBitsFast(n uint8) int {
+func (b *bitReader) get32BitsFast(n uint8) uint32 {
const regMask = 64 - 1
v := uint32((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask))
b.bitsRead += n
- return int(v)
+ return v
+}
+
+func (b *bitReader) get16BitsFast(n uint8) uint16 {
+ const regMask = 64 - 1
+ v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask))
+ b.bitsRead += n
+ return v
}
// fillFast() will make sure at least 32 bits are available.
diff --git a/vendor/github.com/klauspost/compress/zstd/bitwriter.go b/vendor/github.com/klauspost/compress/zstd/bitwriter.go
index 303ae90f9..b36618285 100644
--- a/vendor/github.com/klauspost/compress/zstd/bitwriter.go
+++ b/vendor/github.com/klauspost/compress/zstd/bitwriter.go
@@ -38,7 +38,7 @@ func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
b.nBits += bits
}
-// addBits32NC will add up to 32 bits.
+// addBits32NC will add up to 31 bits.
// It will not check if there is space for them,
// so the caller must ensure that it has flushed recently.
func (b *bitWriter) addBits32NC(value uint32, bits uint8) {
@@ -46,6 +46,26 @@ func (b *bitWriter) addBits32NC(value uint32, bits uint8) {
b.nBits += bits
}
+// addBits64NC will add up to 64 bits.
+// There must be space for 32 bits.
+func (b *bitWriter) addBits64NC(value uint64, bits uint8) {
+ if bits <= 31 {
+ b.addBits32Clean(uint32(value), bits)
+ return
+ }
+ b.addBits32Clean(uint32(value), 32)
+ b.flush32()
+ b.addBits32Clean(uint32(value>>32), bits-32)
+}
+
+// addBits32Clean will add up to 32 bits.
+// It will not check if there is space for them.
+// The input must not contain more bits than specified.
+func (b *bitWriter) addBits32Clean(value uint32, bits uint8) {
+ b.bitContainer |= uint64(value) << (b.nBits & 63)
+ b.nBits += bits
+}
+
// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go
index 8a98c4562..dc587b2c9 100644
--- a/vendor/github.com/klauspost/compress/zstd/blockdec.go
+++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go
@@ -76,12 +76,11 @@ type blockDec struct {
// Window size of the block.
WindowSize uint64
- history chan *history
- input chan struct{}
- result chan decodeOutput
- sequenceBuf []seq
- err error
- decWG sync.WaitGroup
+ history chan *history
+ input chan struct{}
+ result chan decodeOutput
+ err error
+ decWG sync.WaitGroup
// Frame to use for singlethreaded decoding.
// Should not be used by the decoder itself since parent may be another frame.
@@ -512,18 +511,7 @@ func (b *blockDec) decodeCompressed(hist *history) error {
nSeqs = 0x7f00 + int(in[1]) + (int(in[2]) << 8)
in = in[3:]
}
- // Allocate sequences
- if cap(b.sequenceBuf) < nSeqs {
- if b.lowMem {
- b.sequenceBuf = make([]seq, nSeqs)
- } else {
- // Allocate max
- b.sequenceBuf = make([]seq, nSeqs, maxSequences)
- }
- } else {
- // Reuse buffer
- b.sequenceBuf = b.sequenceBuf[:nSeqs]
- }
+
var seqs = &sequenceDecs{}
if nSeqs > 0 {
if len(in) < 1 {
diff --git a/vendor/github.com/klauspost/compress/zstd/blockenc.go b/vendor/github.com/klauspost/compress/zstd/blockenc.go
index 3df185ee4..12e8f6f0b 100644
--- a/vendor/github.com/klauspost/compress/zstd/blockenc.go
+++ b/vendor/github.com/klauspost/compress/zstd/blockenc.go
@@ -51,7 +51,7 @@ func (b *blockEnc) init() {
if cap(b.literals) < maxCompressedBlockSize {
b.literals = make([]byte, 0, maxCompressedBlockSize)
}
- const defSeqs = 200
+ const defSeqs = 2000
if cap(b.sequences) < defSeqs {
b.sequences = make([]seq, 0, defSeqs)
}
@@ -426,7 +426,7 @@ func fuzzFseEncoder(data []byte) int {
return 0
}
enc := fseEncoder{}
- hist := enc.Histogram()[:256]
+ hist := enc.Histogram()
maxSym := uint8(0)
for i, v := range data {
v = v & 63
@@ -722,52 +722,53 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error {
println("Encoded seq", seq, s, "codes:", s.llCode, s.mlCode, s.ofCode, "states:", ll.state, ml.state, of.state, "bits:", llB, mlB, ofB)
}
seq--
- if llEnc.maxBits+mlEnc.maxBits+ofEnc.maxBits <= 32 {
- // No need to flush (common)
- for seq >= 0 {
- s = b.sequences[seq]
- wr.flush32()
- llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
- // tabelog max is 8 for all.
- of.encode(ofB)
- ml.encode(mlB)
- ll.encode(llB)
- wr.flush32()
-
- // We checked that all can stay within 32 bits
- wr.addBits32NC(s.litLen, llB.outBits)
- wr.addBits32NC(s.matchLen, mlB.outBits)
- wr.addBits32NC(s.offset, ofB.outBits)
-
- if debugSequences {
- println("Encoded seq", seq, s)
- }
-
- seq--
- }
- } else {
- for seq >= 0 {
- s = b.sequences[seq]
- wr.flush32()
- llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode]
- // tabelog max is below 8 for each.
- of.encode(ofB)
- ml.encode(mlB)
- ll.encode(llB)
- wr.flush32()
-
- // ml+ll = max 32 bits total
- wr.addBits32NC(s.litLen, llB.outBits)
- wr.addBits32NC(s.matchLen, mlB.outBits)
- wr.flush32()
- wr.addBits32NC(s.offset, ofB.outBits)
-
- if debugSequences {
- println("Encoded seq", seq, s)
- }
-
- seq--
- }
+ // Store sequences in reverse...
+ for seq >= 0 {
+ s = b.sequences[seq]
+
+ ofB := ofTT[s.ofCode]
+ wr.flush32() // tablelog max is below 8 for each, so it will fill max 24 bits.
+ //of.encode(ofB)
+ nbBitsOut := (uint32(of.state) + ofB.deltaNbBits) >> 16
+ dstState := int32(of.state>>(nbBitsOut&15)) + int32(ofB.deltaFindState)
+ wr.addBits16NC(of.state, uint8(nbBitsOut))
+ of.state = of.stateTable[dstState]
+
+ // Accumulate extra bits.
+ outBits := ofB.outBits & 31
+ extraBits := uint64(s.offset & bitMask32[outBits])
+ extraBitsN := outBits
+
+ mlB := mlTT[s.mlCode]
+ //ml.encode(mlB)
+ nbBitsOut = (uint32(ml.state) + mlB.deltaNbBits) >> 16
+ dstState = int32(ml.state>>(nbBitsOut&15)) + int32(mlB.deltaFindState)
+ wr.addBits16NC(ml.state, uint8(nbBitsOut))
+ ml.state = ml.stateTable[dstState]
+
+ outBits = mlB.outBits & 31
+ extraBits = extraBits<<outBits | uint64(s.matchLen&bitMask32[outBits])
+ extraBitsN += outBits
+
+ llB := llTT[s.llCode]
+ //ll.encode(llB)
+ nbBitsOut = (uint32(ll.state) + llB.deltaNbBits) >> 16
+ dstState = int32(ll.state>>(nbBitsOut&15)) + int32(llB.deltaFindState)
+ wr.addBits16NC(ll.state, uint8(nbBitsOut))
+ ll.state = ll.stateTable[dstState]
+
+ outBits = llB.outBits & 31
+ extraBits = extraBits<<outBits | uint64(s.litLen&bitMask32[outBits])
+ extraBitsN += outBits
+
+ wr.flush32()
+ wr.addBits64NC(extraBits, extraBitsN)
+
+ if debugSequences {
+ println("Encoded seq", seq, s)
+ }
+
+ seq--
}
ml.flush(mlEnc.actualTableLog)
of.flush(ofEnc.actualTableLog)
@@ -801,14 +802,13 @@ func (b *blockEnc) genCodes() {
// nothing to do
return
}
-
if len(b.sequences) > math.MaxUint16 {
panic("can only encode up to 64K sequences")
}
// No bounds checks after here:
- llH := b.coders.llEnc.Histogram()[:256]
- ofH := b.coders.ofEnc.Histogram()[:256]
- mlH := b.coders.mlEnc.Histogram()[:256]
+ llH := b.coders.llEnc.Histogram()
+ ofH := b.coders.ofEnc.Histogram()
+ mlH := b.coders.mlEnc.Histogram()
for i := range llH {
llH[i] = 0
}
@@ -820,7 +820,8 @@ func (b *blockEnc) genCodes() {
}
var llMax, ofMax, mlMax uint8
- for i, seq := range b.sequences {
+ for i := range b.sequences {
+ seq := &b.sequences[i]
v := llCode(seq.litLen)
seq.llCode = v
llH[v]++
@@ -844,7 +845,6 @@ func (b *blockEnc) genCodes() {
panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d), matchlen: %d", mlMax, seq.matchLen))
}
}
- b.sequences[i] = seq
}
maxCount := func(a []uint32) int {
var max uint32
diff --git a/vendor/github.com/klauspost/compress/zstd/decodeheader.go b/vendor/github.com/klauspost/compress/zstd/decodeheader.go
index 69736e8d4..5022e71c8 100644
--- a/vendor/github.com/klauspost/compress/zstd/decodeheader.go
+++ b/vendor/github.com/klauspost/compress/zstd/decodeheader.go
@@ -5,6 +5,7 @@ package zstd
import (
"bytes"
+ "encoding/binary"
"errors"
"io"
)
@@ -15,18 +16,50 @@ const HeaderMaxSize = 14 + 3
// Header contains information about the first frame and block within that.
type Header struct {
- // Window Size the window of data to keep while decoding.
- // Will only be set if HasFCS is false.
- WindowSize uint64
+ // SingleSegment specifies whether the data is to be decompressed into a
+ // single contiguous memory segment.
+ // It implies that WindowSize is invalid and that FrameContentSize is valid.
+ SingleSegment bool
- // Frame content size.
- // Expected size of the entire frame.
- FrameContentSize uint64
+ // WindowSize is the window of data to keep while decoding.
+ // Will only be set if SingleSegment is false.
+ WindowSize uint64
// Dictionary ID.
// If 0, no dictionary.
DictionaryID uint32
+ // HasFCS specifies whether FrameContentSize has a valid value.
+ HasFCS bool
+
+ // FrameContentSize is the expected uncompressed size of the entire frame.
+ FrameContentSize uint64
+
+ // Skippable will be true if the frame is meant to be skipped.
+ // This implies that FirstBlock.OK is false.
+ Skippable bool
+
+ // SkippableID is the user-specific ID for the skippable frame.
+ // Valid values are between 0 to 15, inclusive.
+ SkippableID int
+
+ // SkippableSize is the length of the user data to skip following
+ // the header.
+ SkippableSize uint32
+
+ // HeaderSize is the raw size of the frame header.
+ //
+ // For normal frames, it includes the size of the magic number and
+ // the size of the header (per section 3.1.1.1).
+ // It does not include the size for any data blocks (section 3.1.1.2) nor
+ // the size for the trailing content checksum.
+ //
+ // For skippable frames, this counts the size of the magic number
+ // along with the size of the size field of the payload.
+ // It does not include the size of the skippable payload itself.
+ // The total frame size is the HeaderSize plus the SkippableSize.
+ HeaderSize int
+
// First block information.
FirstBlock struct {
// OK will be set if first block could be decoded.
@@ -51,17 +84,9 @@ type Header struct {
CompressedSize int
}
- // Skippable will be true if the frame is meant to be skipped.
- // No other information will be populated.
- Skippable bool
-
// If set there is a checksum present for the block content.
+ // The checksum field at the end is always 4 bytes long.
HasCheckSum bool
-
- // If this is true FrameContentSize will have a valid value
- HasFCS bool
-
- SingleSegment bool
}
// Decode the header from the beginning of the stream.
@@ -71,39 +96,46 @@ type Header struct {
// If there isn't enough input, io.ErrUnexpectedEOF is returned.
// The FirstBlock.OK will indicate if enough information was available to decode the first block header.
func (h *Header) Decode(in []byte) error {
+ *h = Header{}
if len(in) < 4 {
return io.ErrUnexpectedEOF
}
+ h.HeaderSize += 4
b, in := in[:4], in[4:]
if !bytes.Equal(b, frameMagic) {
if !bytes.Equal(b[1:4], skippableFrameMagic) || b[0]&0xf0 != 0x50 {
return ErrMagicMismatch
}
- *h = Header{Skippable: true}
+ if len(in) < 4 {
+ return io.ErrUnexpectedEOF
+ }
+ h.HeaderSize += 4
+ h.Skippable = true
+ h.SkippableID = int(b[0] & 0xf)
+ h.SkippableSize = binary.LittleEndian.Uint32(in)
return nil
}
+
+ // Read Window_Descriptor
+ // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor
if len(in) < 1 {
return io.ErrUnexpectedEOF
}
-
- // Clear output
- *h = Header{}
fhd, in := in[0], in[1:]
+ h.HeaderSize++
h.SingleSegment = fhd&(1<<5) != 0
h.HasCheckSum = fhd&(1<<2) != 0
-
if fhd&(1<<3) != 0 {
return errors.New("reserved bit set on frame header")
}
- // Read Window_Descriptor
- // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor
if !h.SingleSegment {
if len(in) < 1 {
return io.ErrUnexpectedEOF
}
var wd byte
wd, in = in[0], in[1:]
+ h.HeaderSize++
windowLog := 10 + (wd >> 3)
windowBase := uint64(1) << windowLog
windowAdd := (windowBase / 8) * uint64(wd&0x7)
@@ -120,9 +152,7 @@ func (h *Header) Decode(in []byte) error {
return io.ErrUnexpectedEOF
}
b, in = in[:size], in[size:]
- if b == nil {
- return io.ErrUnexpectedEOF
- }
+ h.HeaderSize += int(size)
switch size {
case 1:
h.DictionaryID = uint32(b[0])
@@ -152,9 +182,7 @@ func (h *Header) Decode(in []byte) error {
return io.ErrUnexpectedEOF
}
b, in = in[:fcsSize], in[fcsSize:]
- if b == nil {
- return io.ErrUnexpectedEOF
- }
+ h.HeaderSize += int(fcsSize)
switch fcsSize {
case 1:
h.FrameContentSize = uint64(b[0])
diff --git a/vendor/github.com/klauspost/compress/zstd/enc_base.go b/vendor/github.com/klauspost/compress/zstd/enc_base.go
index 295cd602a..15ae8ee80 100644
--- a/vendor/github.com/klauspost/compress/zstd/enc_base.go
+++ b/vendor/github.com/klauspost/compress/zstd/enc_base.go
@@ -108,11 +108,6 @@ func (e *fastBase) UseBlock(enc *blockEnc) {
e.blk = enc
}
-func (e *fastBase) matchlenNoHist(s, t int32, src []byte) int32 {
- // Extend the match to be as long as possible.
- return int32(matchLen(src[s:], src[t:]))
-}
-
func (e *fastBase) matchlen(s, t int32, src []byte) int32 {
if debugAsserts {
if s < 0 {
@@ -131,9 +126,24 @@ func (e *fastBase) matchlen(s, t int32, src []byte) int32 {
panic(fmt.Sprintf("len(src)-s (%d) > maxCompressedBlockSize (%d)", len(src)-int(s), maxCompressedBlockSize))
}
}
+ a := src[s:]
+ b := src[t:]
+ b = b[:len(a)]
+ end := int32((len(a) >> 3) << 3)
+ for i := int32(0); i < end; i += 8 {
+ if diff := load6432(a, i) ^ load6432(b, i); diff != 0 {
+ return i + int32(bits.TrailingZeros64(diff)>>3)
+ }
+ }
- // Extend the match to be as long as possible.
- return int32(matchLen(src[s:], src[t:]))
+ a = a[end:]
+ b = b[end:]
+ for i := range a {
+ if a[i] != b[i] {
+ return int32(i) + end
+ }
+ }
+ return int32(len(a)) + end
}
// Reset the encoding table.
diff --git a/vendor/github.com/klauspost/compress/zstd/enc_fast.go b/vendor/github.com/klauspost/compress/zstd/enc_fast.go
index f2502629b..5f08a2830 100644
--- a/vendor/github.com/klauspost/compress/zstd/enc_fast.go
+++ b/vendor/github.com/klauspost/compress/zstd/enc_fast.go
@@ -6,8 +6,6 @@ package zstd
import (
"fmt"
- "math"
- "math/bits"
)
const (
@@ -136,20 +134,7 @@ encodeLoop:
// Consider history as well.
var seq seq
var length int32
- // length = 4 + e.matchlen(s+6, repIndex+4, src)
- {
- a := src[s+6:]
- b := src[repIndex+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- length = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- length = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
-
+ length = 4 + e.matchlen(s+6, repIndex+4, src)
seq.matchLen = uint32(length - zstdMinMatch)
// We might be able to match backwards.
@@ -236,20 +221,7 @@ encodeLoop:
}
// Extend the 4-byte match as long as possible.
- //l := e.matchlen(s+4, t+4, src) + 4
- var l int32
- {
- a := src[s+4:]
- b := src[t+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := e.matchlen(s+4, t+4, src) + 4
// Extend backwards
tMin := s - e.maxMatchOff
@@ -286,20 +258,7 @@ encodeLoop:
if o2 := s - offset2; canRepeat && load3232(src, o2) == uint32(cv) {
// We have at least 4 byte match.
// No need to check backwards. We come straight from a match
- //l := 4 + e.matchlen(s+4, o2+4, src)
- var l int32
- {
- a := src[s+4:]
- b := src[o2+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := 4 + e.matchlen(s+4, o2+4, src)
// Store this, since we have it.
nextHash := hashLen(cv, hashLog, tableFastHashLen)
@@ -418,21 +377,7 @@ encodeLoop:
if len(blk.sequences) > 2 && load3232(src, repIndex) == uint32(cv>>16) {
// Consider history as well.
var seq seq
- // length := 4 + e.matchlen(s+6, repIndex+4, src)
- // length := 4 + int32(matchLen(src[s+6:], src[repIndex+4:]))
- var length int32
- {
- a := src[s+6:]
- b := src[repIndex+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- length = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- length = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ length := 4 + e.matchlen(s+6, repIndex+4, src)
seq.matchLen = uint32(length - zstdMinMatch)
@@ -522,21 +467,7 @@ encodeLoop:
panic(fmt.Sprintf("t (%d) < 0 ", t))
}
// Extend the 4-byte match as long as possible.
- //l := e.matchlenNoHist(s+4, t+4, src) + 4
- // l := int32(matchLen(src[s+4:], src[t+4:])) + 4
- var l int32
- {
- a := src[s+4:]
- b := src[t+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := e.matchlen(s+4, t+4, src) + 4
// Extend backwards
tMin := s - e.maxMatchOff
@@ -573,21 +504,7 @@ encodeLoop:
if o2 := s - offset2; len(blk.sequences) > 2 && load3232(src, o2) == uint32(cv) {
// We have at least 4 byte match.
// No need to check backwards. We come straight from a match
- //l := 4 + e.matchlenNoHist(s+4, o2+4, src)
- // l := 4 + int32(matchLen(src[s+4:], src[o2+4:]))
- var l int32
- {
- a := src[s+4:]
- b := src[o2+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := 4 + e.matchlen(s+4, o2+4, src)
// Store this, since we have it.
nextHash := hashLen(cv, hashLog, tableFastHashLen)
@@ -731,19 +648,7 @@ encodeLoop:
// Consider history as well.
var seq seq
var length int32
- // length = 4 + e.matchlen(s+6, repIndex+4, src)
- {
- a := src[s+6:]
- b := src[repIndex+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- length = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- length = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ length = 4 + e.matchlen(s+6, repIndex+4, src)
seq.matchLen = uint32(length - zstdMinMatch)
@@ -831,20 +736,7 @@ encodeLoop:
}
// Extend the 4-byte match as long as possible.
- //l := e.matchlen(s+4, t+4, src) + 4
- var l int32
- {
- a := src[s+4:]
- b := src[t+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := e.matchlen(s+4, t+4, src) + 4
// Extend backwards
tMin := s - e.maxMatchOff
@@ -881,20 +773,7 @@ encodeLoop:
if o2 := s - offset2; canRepeat && load3232(src, o2) == uint32(cv) {
// We have at least 4 byte match.
// No need to check backwards. We come straight from a match
- //l := 4 + e.matchlen(s+4, o2+4, src)
- var l int32
- {
- a := src[s+4:]
- b := src[o2+4:]
- endI := len(a) & (math.MaxInt32 - 7)
- l = int32(endI) + 4
- for i := 0; i < endI; i += 8 {
- if diff := load64(a, i) ^ load64(b, i); diff != 0 {
- l = int32(i+bits.TrailingZeros64(diff)>>3) + 4
- break
- }
- }
- }
+ l := 4 + e.matchlen(s+4, o2+4, src)
// Store this, since we have it.
nextHash := hashLen(cv, hashLog, tableFastHashLen)
diff --git a/vendor/github.com/klauspost/compress/zstd/encoder_options.go b/vendor/github.com/klauspost/compress/zstd/encoder_options.go
index 7d29e1d68..5f2e1d020 100644
--- a/vendor/github.com/klauspost/compress/zstd/encoder_options.go
+++ b/vendor/github.com/klauspost/compress/zstd/encoder_options.go
@@ -24,6 +24,7 @@ type encoderOptions struct {
allLitEntropy bool
customWindow bool
customALEntropy bool
+ customBlockSize bool
lowMem bool
dict *dict
}
@@ -33,7 +34,7 @@ func (o *encoderOptions) setDefault() {
concurrent: runtime.GOMAXPROCS(0),
crc: true,
single: nil,
- blockSize: 1 << 16,
+ blockSize: maxCompressedBlockSize,
windowSize: 8 << 20,
level: SpeedDefault,
allLitEntropy: true,
@@ -106,6 +107,7 @@ func WithWindowSize(n int) EOption {
o.customWindow = true
if o.blockSize > o.windowSize {
o.blockSize = o.windowSize
+ o.customBlockSize = true
}
return nil
}
@@ -188,10 +190,9 @@ func EncoderLevelFromZstd(level int) EncoderLevel {
return SpeedDefault
case level >= 6 && level < 10:
return SpeedBetterCompression
- case level >= 10:
+ default:
return SpeedBestCompression
}
- return SpeedDefault
}
// String provides a string representation of the compression level.
@@ -222,6 +223,9 @@ func WithEncoderLevel(l EncoderLevel) EOption {
switch o.level {
case SpeedFastest:
o.windowSize = 4 << 20
+ if !o.customBlockSize {
+ o.blockSize = 1 << 16
+ }
case SpeedDefault:
o.windowSize = 8 << 20
case SpeedBetterCompression:
diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder.go
index e6d3d49b3..bb3d4fd6c 100644
--- a/vendor/github.com/klauspost/compress/zstd/fse_decoder.go
+++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder.go
@@ -379,7 +379,7 @@ func (s decSymbol) final() (int, uint8) {
// This can only be used if no symbols are 0 bits.
// At least tablelog bits must be available in the bit reader.
func (s *fseState) nextFast(br *bitReader) (uint32, uint8) {
- lowBits := uint16(br.getBitsFast(s.state.nbBits()))
+ lowBits := br.get16BitsFast(s.state.nbBits())
s.state = s.dt[s.state.newState()+lowBits]
return s.state.baseline(), s.state.addBits()
}
diff --git a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go
index b4757ee3f..5442061b1 100644
--- a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go
+++ b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go
@@ -62,9 +62,8 @@ func (s symbolTransform) String() string {
// To indicate that you have populated the histogram call HistogramFinished
// with the value of the highest populated symbol, as well as the number of entries
// in the most populated entry. These are accepted at face value.
-// The returned slice will always be length 256.
-func (s *fseEncoder) Histogram() []uint32 {
- return s.count[:]
+func (s *fseEncoder) Histogram() *[256]uint32 {
+ return &s.count
}
// HistogramFinished can be called to indicate that the histogram has been populated.
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s
index be8db5bf7..cea178561 100644
--- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s
@@ -1,6 +1,7 @@
// +build !appengine
// +build gc
// +build !purego
+// +build !noasm
#include "textflag.h"
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s
new file mode 100644
index 000000000..4d64a17d6
--- /dev/null
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s
@@ -0,0 +1,186 @@
+// +build gc,!purego,!noasm
+
+#include "textflag.h"
+
+// Register allocation.
+#define digest R1
+#define h R2 // Return value.
+#define p R3 // Input pointer.
+#define len R4
+#define nblocks R5 // len / 32.
+#define prime1 R7
+#define prime2 R8
+#define prime3 R9
+#define prime4 R10
+#define prime5 R11
+#define v1 R12
+#define v2 R13
+#define v3 R14
+#define v4 R15
+#define x1 R20
+#define x2 R21
+#define x3 R22
+#define x4 R23
+
+#define round(acc, x) \
+ MADD prime2, acc, x, acc \
+ ROR $64-31, acc \
+ MUL prime1, acc \
+
+// x = round(0, x).
+#define round0(x) \
+ MUL prime2, x \
+ ROR $64-31, x \
+ MUL prime1, x \
+
+#define mergeRound(x) \
+ round0(x) \
+ EOR x, h \
+ MADD h, prime4, prime1, h \
+
+// Update v[1-4] with 32-byte blocks. Assumes len >= 32.
+#define blocksLoop() \
+ LSR $5, len, nblocks \
+ PCALIGN $16 \
+ loop: \
+ LDP.P 32(p), (x1, x2) \
+ round(v1, x1) \
+ LDP -16(p), (x3, x4) \
+ round(v2, x2) \
+ SUB $1, nblocks \
+ round(v3, x3) \
+ round(v4, x4) \
+ CBNZ nblocks, loop \
+
+// The primes are repeated here to ensure that they're stored
+// in a contiguous array, so we can load them with LDP.
+DATA primes<> +0(SB)/8, $11400714785074694791
+DATA primes<> +8(SB)/8, $14029467366897019727
+DATA primes<>+16(SB)/8, $1609587929392839161
+DATA primes<>+24(SB)/8, $9650029242287828579
+DATA primes<>+32(SB)/8, $2870177450012600261
+GLOBL primes<>(SB), NOPTR+RODATA, $40
+
+// func Sum64(b []byte) uint64
+TEXT ·Sum64(SB), NOFRAME+NOSPLIT, $0-32
+ LDP b_base+0(FP), (p, len)
+
+ LDP primes<> +0(SB), (prime1, prime2)
+ LDP primes<>+16(SB), (prime3, prime4)
+ MOVD primes<>+32(SB), prime5
+
+ CMP $32, len
+ CSEL LO, prime5, ZR, h // if len < 32 { h = prime5 } else { h = 0 }
+ BLO afterLoop
+
+ ADD prime1, prime2, v1
+ MOVD prime2, v2
+ MOVD $0, v3
+ NEG prime1, v4
+
+ blocksLoop()
+
+ ROR $64-1, v1, x1
+ ROR $64-7, v2, x2
+ ADD x1, x2
+ ROR $64-12, v3, x3
+ ROR $64-18, v4, x4
+ ADD x3, x4
+ ADD x2, x4, h
+
+ mergeRound(v1)
+ mergeRound(v2)
+ mergeRound(v3)
+ mergeRound(v4)
+
+afterLoop:
+ ADD len, h
+
+ TBZ $4, len, try8
+ LDP.P 16(p), (x1, x2)
+
+ round0(x1)
+ ROR $64-27, h
+ EOR x1 @> 64-27, h, h
+ MADD h, prime4, prime1, h
+
+ round0(x2)
+ ROR $64-27, h
+ EOR x2 @> 64-27, h
+ MADD h, prime4, prime1, h
+
+try8:
+ TBZ $3, len, try4
+ MOVD.P 8(p), x1
+
+ round0(x1)
+ ROR $64-27, h
+ EOR x1 @> 64-27, h
+ MADD h, prime4, prime1, h
+
+try4:
+ TBZ $2, len, try2
+ MOVWU.P 4(p), x2
+
+ MUL prime1, x2
+ ROR $64-23, h
+ EOR x2 @> 64-23, h
+ MADD h, prime3, prime2, h
+
+try2:
+ TBZ $1, len, try1
+ MOVHU.P 2(p), x3
+ AND $255, x3, x1
+ LSR $8, x3, x2
+
+ MUL prime5, x1
+ ROR $64-11, h
+ EOR x1 @> 64-11, h
+ MUL prime1, h
+
+ MUL prime5, x2
+ ROR $64-11, h
+ EOR x2 @> 64-11, h
+ MUL prime1, h
+
+try1:
+ TBZ $0, len, end
+ MOVBU (p), x4
+
+ MUL prime5, x4
+ ROR $64-11, h
+ EOR x4 @> 64-11, h
+ MUL prime1, h
+
+end:
+ EOR h >> 33, h
+ MUL prime2, h
+ EOR h >> 29, h
+ MUL prime3, h
+ EOR h >> 32, h
+
+ MOVD h, ret+24(FP)
+ RET
+
+// func writeBlocks(d *Digest, b []byte) int
+//
+// Assumes len(b) >= 32.
+TEXT ·writeBlocks(SB), NOFRAME+NOSPLIT, $0-40
+ LDP primes<>(SB), (prime1, prime2)
+
+ // Load state. Assume v[1-4] are stored contiguously.
+ MOVD d+0(FP), digest
+ LDP 0(digest), (v1, v2)
+ LDP 16(digest), (v3, v4)
+
+ LDP b_base+8(FP), (p, len)
+
+ blocksLoop()
+
+ // Store updated state.
+ STP (v1, v2), 0(digest)
+ STP (v3, v4), 16(digest)
+
+ BIC $31, len
+ MOVD len, ret+32(FP)
+ RET
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go
index 0ae847f75..1a1fac9c2 100644
--- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go
@@ -1,5 +1,9 @@
-//go:build !appengine && gc && !purego
-// +build !appengine,gc,!purego
+//go:build (amd64 || arm64) && !appengine && gc && !purego && !noasm
+// +build amd64 arm64
+// +build !appengine
+// +build gc
+// +build !purego
+// +build !noasm
package xxhash
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go
index 1f52f296e..209cb4a99 100644
--- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go
@@ -1,5 +1,5 @@
-//go:build !amd64 || appengine || !gc || purego
-// +build !amd64 appengine !gc purego
+//go:build (!amd64 && !arm64) || appengine || !gc || purego || noasm
+// +build !amd64,!arm64 appengine !gc purego noasm
package xxhash
diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go
index 1dd39e63b..bc731e4cb 100644
--- a/vendor/github.com/klauspost/compress/zstd/seqdec.go
+++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go
@@ -278,7 +278,7 @@ func (s *sequenceDecs) decode(seqs int, br *bitReader, hist []byte) error {
mlState = mlTable[mlState.newState()&maxTableMask]
ofState = ofTable[ofState.newState()&maxTableMask]
} else {
- bits := br.getBitsFast(nBits)
+ bits := br.get32BitsFast(nBits)
lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31))
llState = llTable[(llState.newState()+lowBits)&maxTableMask]
@@ -326,7 +326,7 @@ func (s *sequenceDecs) updateAlt(br *bitReader) {
s.offsets.state.state = s.offsets.state.dt[c.newState()]
return
}
- bits := br.getBitsFast(nBits)
+ bits := br.get32BitsFast(nBits)
lowBits := uint16(bits >> ((c.nbBits() + b.nbBits()) & 31))
s.litLengths.state.state = s.litLengths.state.dt[a.newState()+lowBits]
diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod
deleted file mode 100644
index 3dd09c9fb..000000000
--- a/vendor/github.com/mtrmac/gpgme/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/mtrmac/gpgme
-
-go 1.11
diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
index 6a7a91e55..c0e879448 100644
--- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
+++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
@@ -15,7 +15,7 @@ type Spec struct {
// Mounts configures additional mounts (on top of Root).
Mounts []Mount `json:"mounts,omitempty"`
// Hooks configures callbacks for container lifecycle events.
- Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"`
+ Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris,zos"`
// Annotations contains arbitrary metadata for the container.
Annotations map[string]string `json:"annotations,omitempty"`
@@ -27,6 +27,8 @@ type Spec struct {
Windows *Windows `json:"windows,omitempty" platform:"windows"`
// VM specifies configuration for virtual-machine-based containers.
VM *VM `json:"vm,omitempty" platform:"vm"`
+ // ZOS is platform-specific configuration for z/OS based containers.
+ ZOS *ZOS `json:"zos,omitempty" platform:"zos"`
}
// Process contains information to start a specific application inside the container.
@@ -49,7 +51,7 @@ type Process struct {
// Capabilities are Linux capabilities that are kept for the process.
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
// Rlimits specifies rlimit options to apply to the process.
- Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"`
+ Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris,zos"`
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
// ApparmorProfile specifies the apparmor profile for the container.
@@ -86,11 +88,11 @@ type Box struct {
// User specifies specific user (and group) information for the container process.
type User struct {
// UID is the user id.
- UID uint32 `json:"uid" platform:"linux,solaris"`
+ UID uint32 `json:"uid" platform:"linux,solaris,zos"`
// GID is the group id.
- GID uint32 `json:"gid" platform:"linux,solaris"`
+ GID uint32 `json:"gid" platform:"linux,solaris,zos"`
// Umask is the umask for the init process.
- Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
+ Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris,zos"`
// AdditionalGids are additional group ids set for the container's process.
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
// Username is the user name.
@@ -110,7 +112,7 @@ type Mount struct {
// Destination is the absolute path where the mount will be placed in the container.
Destination string `json:"destination"`
// Type specifies the mount kind.
- Type string `json:"type,omitempty" platform:"linux,solaris"`
+ Type string `json:"type,omitempty" platform:"linux,solaris,zos"`
// Source specifies the source path of the mount.
Source string `json:"source,omitempty"`
// Options are fstab style mount options.
@@ -178,7 +180,7 @@ type Linux struct {
// MountLabel specifies the selinux context for the mounts in the container.
MountLabel string `json:"mountLabel,omitempty"`
// IntelRdt contains Intel Resource Director Technology (RDT) information for
- // handling resource constraints (e.g., L3 cache, memory bandwidth) for the container
+ // handling resource constraints and monitoring metrics (e.g., L3 cache, memory bandwidth) for the container
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
// Personality contains configuration for the Linux personality syscall
Personality *LinuxPersonality `json:"personality,omitempty"`
@@ -683,8 +685,9 @@ type LinuxSyscall struct {
Args []LinuxSeccompArg `json:"args,omitempty"`
}
-// LinuxIntelRdt has container runtime resource constraints for Intel RDT
-// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
+// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
+// features and flags enabling Intel RDT CMT and MBM features.
+// Intel RDT features are available in Linux 4.14 and newer kernel versions.
type LinuxIntelRdt struct {
// The identity for RDT Class of Service
ClosID string `json:"closID,omitempty"`
@@ -697,4 +700,36 @@ type LinuxIntelRdt struct {
// The unit of memory bandwidth is specified in "percentages" by
// default, and in "MBps" if MBA Software Controller is enabled.
MemBwSchema string `json:"memBwSchema,omitempty"`
+
+ // EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
+ // the last-level cache (LLC) occupancy for the container.
+ EnableCMT bool `json:"enableCMT,omitempty"`
+
+ // EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
+ // total and local memory bandwidth for the container.
+ EnableMBM bool `json:"enableMBM,omitempty"`
+}
+
+// ZOS contains platform-specific configuration for z/OS based containers.
+type ZOS struct {
+ // Devices are a list of device nodes that are created for the container
+ Devices []ZOSDevice `json:"devices,omitempty"`
+}
+
+// ZOSDevice represents the mknod information for a z/OS special device file
+type ZOSDevice struct {
+ // Path to the device.
+ Path string `json:"path"`
+ // Device type, block, char, etc.
+ Type string `json:"type"`
+ // Major is the device's major number.
+ Major int64 `json:"major"`
+ // Minor is the device's minor number.
+ Minor int64 `json:"minor"`
+ // FileMode permission bits for the device.
+ FileMode *os.FileMode `json:"fileMode,omitempty"`
+ // UID of the device.
+ UID *uint32 `json:"uid,omitempty"`
+ // Gid of the device.
+ GID *uint32 `json:"gid,omitempty"`
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/config.go b/vendor/github.com/opencontainers/runtime-tools/generate/config.go
index f68bdde37..48f281d28 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/config.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/config.go
@@ -123,6 +123,13 @@ func (g *Generator) initConfigLinuxResourcesPids() {
}
}
+func (g *Generator) initConfigLinuxResourcesUnified() {
+ g.initConfigLinuxResources()
+ if g.Config.Linux.Resources.Unified == nil {
+ g.Config.Linux.Resources.Unified = map[string]string{}
+ }
+}
+
func (g *Generator) initConfigSolaris() {
g.initConfig()
if g.Config.Solaris == nil {
@@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
g.Config.VM = &rspec.VM{}
}
}
-
-func (g *Generator) initConfigVMHypervisor() {
- g.initConfigVM()
- if &g.Config.VM.Hypervisor == nil {
- g.Config.VM.Hypervisor = rspec.VMHypervisor{}
- }
-}
-
-func (g *Generator) initConfigVMKernel() {
- g.initConfigVM()
- if &g.Config.VM.Kernel == nil {
- g.Config.VM.Kernel = rspec.VMKernel{}
- }
-}
-
-func (g *Generator) initConfigVMImage() {
- g.initConfigVM()
- if &g.Config.VM.Image == nil {
- g.Config.VM.Image = rspec.VMImage{}
- }
-}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go b/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
index 70b175362..be1f027bf 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
@@ -604,6 +604,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
g.Config.Linux.CgroupsPath = path
}
+// SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
+func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
+ g.initConfigLinuxIntelRdt()
+ g.Config.Linux.IntelRdt.ClosID = clos
+}
+
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
g.initConfigLinuxIntelRdt()
@@ -851,6 +857,28 @@ func (g *Generator) DropLinuxResourcesHugepageLimit(pageSize string) {
}
}
+// AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
+func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
+ g.initConfigLinuxResourcesUnified()
+ for k, v := range unified {
+ g.Config.Linux.Resources.Unified[k] = v
+ }
+}
+
+// AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
+func (g *Generator) AddLinuxResourcesUnified(key, val string) {
+ g.initConfigLinuxResourcesUnified()
+ g.Config.Linux.Resources.Unified[key] = val
+}
+
+// DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
+func (g *Generator) DropLinuxResourcesUnified(key string) {
+ if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
+ return
+ }
+ delete(g.Config.Linux.Resources.Unified, key)
+}
+
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
g.initConfigLinuxResourcesMemory()
@@ -1025,10 +1053,9 @@ func (g *Generator) ClearPreStartHooks() {
}
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
-func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
+func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
- return nil
}
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
@@ -1040,10 +1067,9 @@ func (g *Generator) ClearPostStopHooks() {
}
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
-func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
+func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
- return nil
}
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
@@ -1055,10 +1081,9 @@ func (g *Generator) ClearPostStartHooks() {
}
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
-func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
+func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
- return nil
}
// AddMount adds a mount into g.Config.Mounts.
@@ -1560,12 +1585,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
return
}
}
- return
}
-// strPtr returns the pointer pointing to the string s.
-func strPtr(s string) *string { return &s }
-
// SetSyscallAction adds rules for syscalls with the specified action
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
g.initConfigLinuxSeccomp()
@@ -1691,14 +1712,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
}
- g.initConfigVMHypervisor()
+ g.initConfigVM()
g.Config.VM.Hypervisor.Path = path
return nil
}
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
- g.initConfigVMHypervisor()
+ g.initConfigVM()
g.Config.VM.Hypervisor.Parameters = parameters
}
@@ -1707,14 +1728,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("kernelPath %v is not an absolute path", path)
}
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.Path = path
return nil
}
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
func (g *Generator) SetVMKernelParameters(parameters []string) {
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.Parameters = parameters
}
@@ -1723,7 +1744,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
if !strings.HasPrefix(initrd, "/") {
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
}
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.InitRD = initrd
return nil
}
@@ -1733,7 +1754,7 @@ func (g *Generator) SetVMImagePath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("imagePath %v is not an absolute path", path)
}
- g.initConfigVMImage()
+ g.initConfigVM()
g.Config.VM.Image.Path = path
return nil
}
@@ -1749,7 +1770,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
default:
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
}
- g.initConfigVMImage()
+ g.initConfigVM()
g.Config.VM.Image.Format = format
return nil
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
index eade5718e..f28d8f587 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
@@ -4,9 +4,4 @@ const (
seccompOverwrite = "overwrite"
seccompAppend = "append"
nothing = "nothing"
- kill = "kill"
- trap = "trap"
- trace = "trace"
- allow = "allow"
- errno = "errno"
)
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
index 311587437..93472fba0 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package seccomp
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
index 589b81c16..b8c1bc26e 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package seccomp
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
index dbf2aec1c..5e84653a9 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
@@ -92,22 +92,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1, config2)
}
-func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
- samename := sameName(config1, config2)
- sameAction := sameAction(config1, config2)
- sameArgs := sameArgs(config1, config2)
-
- return samename && !sameAction && sameArgs
-}
-
-func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
- samename := sameName(config1, config2)
- sameAction := sameAction(config1, config2)
- sameArgs := sameArgs(config1, config2)
-
- return samename && sameAction && !sameArgs
-}
-
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1.Names, config2.Names)
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
index 9c3710529..2d3d42bce 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
@@ -131,9 +131,8 @@ func JSONSchemaURL(version string) (url string, err error) {
if err != nil {
return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
}
- configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2
- if ver.Compare(configRenamedToConfigSchemaVersion) == -1 {
- return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion)
+ if ver.LT(semver.Version{Major: 1, Minor: 0, Patch: 2}) {
+ return "", errors.New("unsupported configuration version (older than 1.0.2)")
}
return fmt.Sprintf(configSchemaTemplate, version), nil
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
index dcefafae7..6f1b28218 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package validate
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
index f150c326c..313ec3995 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package validate
diff --git a/vendor/github.com/openshift/imagebuilder/.travis.yml b/vendor/github.com/openshift/imagebuilder/.travis.yml
index 97b530b4f..ff6afee5a 100644
--- a/vendor/github.com/openshift/imagebuilder/.travis.yml
+++ b/vendor/github.com/openshift/imagebuilder/.travis.yml
@@ -1,8 +1,8 @@
language: go
go:
- - "1.9"
- - "1.10"
+ - "1.16"
+ - "1.17"
install:
diff --git a/vendor/github.com/openshift/imagebuilder/builder.go b/vendor/github.com/openshift/imagebuilder/builder.go
index df5269904..b0e9d4f51 100644
--- a/vendor/github.com/openshift/imagebuilder/builder.go
+++ b/vendor/github.com/openshift/imagebuilder/builder.go
@@ -303,6 +303,9 @@ type Builder struct {
PendingCopies []Copy
Warnings []string
+ // Raw platform string specified with `FROM --platform` of the stage
+ // It's up to the implementation or client to parse and use this field
+ Platform string
}
func NewBuilder(args map[string]string) *Builder {
@@ -470,7 +473,7 @@ func (b *Builder) FromImage(image *docker.Image, node *parser.Node) error {
b.RunConfig.Env = nil
// Check to see if we have a default PATH, note that windows won't
- // have one as its set by HCS
+ // have one as it's set by HCS
if runtime.GOOS != "windows" && !hasEnvName(b.Env, "PATH") {
b.RunConfig.Env = append(b.RunConfig.Env, "PATH="+defaultPathEnv)
}
diff --git a/vendor/github.com/openshift/imagebuilder/dispatchers.go b/vendor/github.com/openshift/imagebuilder/dispatchers.go
index 0d82136e7..fd05f031c 100644
--- a/vendor/github.com/openshift/imagebuilder/dispatchers.go
+++ b/vendor/github.com/openshift/imagebuilder/dispatchers.go
@@ -234,6 +234,20 @@ func from(b *Builder, args []string, attributes map[string]bool, flagArgs []stri
return fmt.Errorf("Windows does not support FROM scratch")
}
}
+ userArgs := mergeEnv(envMapAsSlice(b.Args), b.Env)
+ for _, a := range flagArgs {
+ arg, err := ProcessWord(a, userArgs)
+ if err != nil {
+ return err
+ }
+ switch {
+ case strings.HasPrefix(arg, "--platform="):
+ platformString := strings.TrimPrefix(arg, "--platform=")
+ b.Platform = platformString
+ default:
+ return fmt.Errorf("FROM only supports the --platform flag")
+ }
+ }
b.RunConfig.Image = name
// TODO: handle onbuild
return nil
@@ -573,65 +587,63 @@ var targetArgs = []string{"TARGETOS", "TARGETARCH", "TARGETVARIANT"}
// to builder using the --build-arg flag for expansion/subsitution or passing to 'run'.
// Dockerfile author may optionally set a default value of this variable.
func arg(b *Builder, args []string, attributes map[string]bool, flagArgs []string, original string) error {
- if len(args) != 1 {
- return fmt.Errorf("ARG requires exactly one argument definition")
- }
-
var (
name string
value string
hasDefault bool
)
- arg := args[0]
- // 'arg' can just be a name or name-value pair. Note that this is different
- // from 'env' that handles the split of name and value at the parser level.
- // The reason for doing it differently for 'arg' is that we support just
- // defining an arg and not assign it a value (while 'env' always expects a
- // name-value pair). If possible, it will be good to harmonize the two.
- if strings.Contains(arg, "=") {
- parts := strings.SplitN(arg, "=", 2)
- name = parts[0]
- value = parts[1]
- hasDefault = true
- if name == "TARGETPLATFORM" {
- p, err := platforms.Parse(value)
- if err != nil {
- return fmt.Errorf("error parsing TARGETPLATFORM argument")
- }
- for _, val := range targetArgs {
- b.AllowedArgs[val] = true
- }
- b.Args["TARGETPLATFORM"] = p.OS + "/" + p.Architecture
- b.Args["TARGETOS"] = p.OS
- b.Args["TARGETARCH"] = p.Architecture
- b.Args["TARGETVARIANT"] = p.Variant
- if p.Variant != "" {
- b.Args["TARGETPLATFORM"] = b.Args["TARGETPLATFORM"] + "/" + p.Variant
+ for _, argument := range args {
+ arg := argument
+ // 'arg' can just be a name or name-value pair. Note that this is different
+ // from 'env' that handles the split of name and value at the parser level.
+ // The reason for doing it differently for 'arg' is that we support just
+ // defining an arg and not assign it a value (while 'env' always expects a
+ // name-value pair). If possible, it will be good to harmonize the two.
+ if strings.Contains(arg, "=") {
+ parts := strings.SplitN(arg, "=", 2)
+ name = parts[0]
+ value = parts[1]
+ hasDefault = true
+ if name == "TARGETPLATFORM" {
+ p, err := platforms.Parse(value)
+ if err != nil {
+ return fmt.Errorf("error parsing TARGETPLATFORM argument")
+ }
+ for _, val := range targetArgs {
+ b.AllowedArgs[val] = true
+ }
+ b.Args["TARGETPLATFORM"] = p.OS + "/" + p.Architecture
+ b.Args["TARGETOS"] = p.OS
+ b.Args["TARGETARCH"] = p.Architecture
+ b.Args["TARGETVARIANT"] = p.Variant
+ if p.Variant != "" {
+ b.Args["TARGETPLATFORM"] = b.Args["TARGETPLATFORM"] + "/" + p.Variant
+ }
}
+ } else if val, ok := builtinBuildArgs[arg]; ok {
+ name = arg
+ value = val
+ hasDefault = true
+ } else {
+ name = arg
+ hasDefault = false
}
- } else if val, ok := builtinBuildArgs[arg]; ok {
- name = arg
- value = val
- hasDefault = true
- } else {
- name = arg
- hasDefault = false
- }
- // add the arg to allowed list of build-time args from this step on.
- b.AllowedArgs[name] = true
+ // add the arg to allowed list of build-time args from this step on.
+ b.AllowedArgs[name] = true
- // If there is still no default value, a value can be assigned from the heading args
- if val, ok := b.HeadingArgs[name]; ok && !hasDefault {
- b.Args[name] = val
- }
+ // If there is still no default value, a value can be assigned from the heading args
+ if val, ok := b.HeadingArgs[name]; ok && !hasDefault {
+ b.Args[name] = val
+ }
- // If there is a default value associated with this arg then add it to the
- // b.buildArgs, later default values for the same arg override earlier ones.
- // The args passed to builder (UserArgs) override the default value of 'arg'
- // Don't add them here as they were already set in NewBuilder.
- if _, ok := b.UserArgs[name]; !ok && hasDefault {
- b.Args[name] = value
+ // If there is a default value associated with this arg then add it to the
+ // b.buildArgs, later default values for the same arg override earlier ones.
+ // The args passed to builder (UserArgs) override the default value of 'arg'
+ // Don't add them here as they were already set in NewBuilder.
+ if _, ok := b.UserArgs[name]; !ok && hasDefault {
+ b.Args[name] = value
+ }
}
return nil
diff --git a/vendor/github.com/openshift/imagebuilder/go.mod b/vendor/github.com/openshift/imagebuilder/go.mod
new file mode 100644
index 000000000..72dc62448
--- /dev/null
+++ b/vendor/github.com/openshift/imagebuilder/go.mod
@@ -0,0 +1,18 @@
+module github.com/openshift/imagebuilder
+
+go 1.16
+
+require (
+ github.com/containerd/containerd v1.5.9
+ github.com/containers/storage v1.37.0
+ github.com/docker/distribution v2.7.1+incompatible
+ github.com/docker/docker v20.10.12+incompatible
+ github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 // indirect
+ github.com/fsouza/go-dockerclient v1.7.7
+ github.com/pkg/errors v0.9.1
+ github.com/sirupsen/logrus v1.8.1
+ github.com/stretchr/testify v1.7.0
+ golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
+ k8s.io/klog v1.0.0
+)
diff --git a/vendor/github.com/openshift/imagebuilder/go.sum b/vendor/github.com/openshift/imagebuilder/go.sum
new file mode 100644
index 000000000..612540261
--- /dev/null
+++ b/vendor/github.com/openshift/imagebuilder/go.sum
@@ -0,0 +1,1003 @@
+bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+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=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
+github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
+github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
+github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
+github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
+github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
+github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
+github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
+github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
+github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
+github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
+github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
+github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
+github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
+github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M=
+github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
+github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
+github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
+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.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
+github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+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/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
+github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
+github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
+github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
+github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
+github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
+github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
+github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
+github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
+github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
+github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
+github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
+github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
+github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
+github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E=
+github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
+github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
+github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
+github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
+github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
+github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
+github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
+github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
+github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
+github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
+github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
+github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
+github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
+github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
+github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
+github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
+github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
+github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
+github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
+github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4=
+github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ=
+github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
+github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
+github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
+github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8=
+github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
+github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
+github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
+github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
+github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
+github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU=
+github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
+github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
+github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
+github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
+github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
+github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
+github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
+github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
+github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
+github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
+github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
+github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
+github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
+github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
+github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
+github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
+github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
+github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
+github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
+github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
+github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw=
+github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y=
+github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
+github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
+github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
+github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
+github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4=
+github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
+github.com/containers/storage v1.37.0 h1:HVhDsur6sx889ZIZ1d1kEiOzv3gsr5q0diX2VZmOdSg=
+github.com/containers/storage v1.37.0/go.mod h1:kqeJeS0b7DO2ZT1nVWs0XufrmPFbgV3c+Q/45RlH6r4=
+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-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
+github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+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/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
+github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+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 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/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
+github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
+github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
+github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
+github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
+github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y=
+github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q=
+github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
+github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
+github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
+github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
+github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
+github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsouza/go-dockerclient v1.7.7 h1:/pLili4Sj42vpzNkjqag8vpsN0ObuusT1EH/MvGX9+4=
+github.com/fsouza/go-dockerclient v1.7.7/go.mod h1:njNCXvoZj3sLPjf3yO0DPHf1mdLdCPDYPc14GskKA4Y=
+github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
+github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
+github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
+github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
+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-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
+github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
+github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
+github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
+github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
+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/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+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/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+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/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/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/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+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/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
+github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/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-middleware v1.0.1-0.20190118093823-f849b5445de4/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/grpc-ecosystem/grpc-gateway v1.9.5/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/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/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
+github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+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=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+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-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
+github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+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/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
+github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
+github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
+github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
+github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM=
+github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
+github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
+github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
+github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
+github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/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/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+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 v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
+github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/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.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
+github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
+github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
+github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
+github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
+github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
+github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
+github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
+github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+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/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+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/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+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/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+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.0-20190522114515-bc1a522cf7b1/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/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+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 v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+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/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+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.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v1.0.0/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-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
+github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
+github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+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/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
+github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
+github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+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/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
+github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+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/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
+github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
+github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
+github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
+github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
+github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+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/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=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
+github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
+github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
+go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+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-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+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=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+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-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-20190503192946-f4e77d36d62c/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-20190619014844-b5b0513f8c1b/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-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs=
+golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-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-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/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-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
+golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/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-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/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-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+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-20190621195816-6e04913cbbac/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-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+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/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8=
+google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+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-20141024133853-64131543e789/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+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.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+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=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
+gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
+gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
+k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
+k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
+k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
+k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
+k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
+k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
+k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
+k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
+k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
+k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
+k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
+k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
+k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
+k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
+k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
+k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
+k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
+k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
+k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+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/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
+k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
+k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
+k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
+sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/vendor/github.com/openshift/imagebuilder/internals.go b/vendor/github.com/openshift/imagebuilder/internals.go
index f33dc70bb..d4b953903 100644
--- a/vendor/github.com/openshift/imagebuilder/internals.go
+++ b/vendor/github.com/openshift/imagebuilder/internals.go
@@ -52,7 +52,7 @@ func hasSlash(input string) bool {
// makeAbsolute ensures that the provided path is absolute.
func makeAbsolute(dest, workingDir string) string {
- // Twiddle the destination when its a relative path - meaning, make it
+ // Twiddle the destination when it's a relative path - meaning, make it
// relative to the WORKINGDIR
if dest == "." {
if !hasSlash(workingDir) {
diff --git a/vendor/github.com/openshift/imagebuilder/vendor.conf b/vendor/github.com/openshift/imagebuilder/vendor.conf
deleted file mode 100644
index 8074ce80a..000000000
--- a/vendor/github.com/openshift/imagebuilder/vendor.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
-github.com/containerd/containerd v1.3.0
-github.com/containers/storage v1.2
-github.com/docker/docker b68221c37ee597950364788204546f9c9d0e46a1
-github.com/docker/go-connections 97c2040d34dfae1d1b1275fa3a78dbdd2f41cf7e
-github.com/docker/go-units 2fb04c6466a548a03cb009c5569ee1ab1e35398e
-github.com/fsouza/go-dockerclient openshift-4.0 https://github.com/openshift/go-dockerclient.git
-github.com/gogo/protobuf c5a62797aee0054613cc578653a16c6237fef080
-github.com/konsorten/go-windows-terminal-sequences f55edac94c9bbba5d6182a4be46d86a2c9b5b50e
-github.com/Microsoft/go-winio 1a8911d1ed007260465c3bfbbc785ac6915a0bb8
-github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
-github.com/opencontainers/go-digest ac19fd6e7483ff933754af248d80be865e543d22
-github.com/opencontainers/image-spec 243ea084a44451d27322fed02b682d99e2af3ba9
-github.com/opencontainers/runc 923a8f8a9a07aceada5fc48c4d37e905d9b019b5
-github.com/pkg/errors 27936f6d90f9c8e1145f11ed52ffffbfdb9e0af7
-github.com/pquerna/ffjson d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac
-github.com/sirupsen/logrus d7b6bf5e4d26448fd977d07d745a2a66097ddecb
-golang.org/x/crypto ff983b9c42bc9fbf91556e191cc8efb585c16908
-golang.org/x/net 45ffb0cd1ba084b73e26dee67e667e1be5acce83
-golang.org/x/sys 7fbe1cd0fcc20051e1fcb87fbabec4a1bacaaeba
-k8s.io/klog 8e90cee79f823779174776412c13478955131846
-google.golang.org/grpc 6eaf6f47437a6b4e2153a190160ef39a92c7eceb # v1.23.0
-github.com/golang/protobuf v1.2.0
-google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
-
diff --git a/vendor/github.com/mtrmac/gpgme/.appveyor.yml b/vendor/github.com/proglottis/gpgme/.appveyor.yml
index 2fdc09ab5..2fdc09ab5 100644
--- a/vendor/github.com/mtrmac/gpgme/.appveyor.yml
+++ b/vendor/github.com/proglottis/gpgme/.appveyor.yml
diff --git a/vendor/github.com/mtrmac/gpgme/.gitignore b/vendor/github.com/proglottis/gpgme/.gitignore
index 0210b26e0..0210b26e0 100644
--- a/vendor/github.com/mtrmac/gpgme/.gitignore
+++ b/vendor/github.com/proglottis/gpgme/.gitignore
diff --git a/vendor/github.com/mtrmac/gpgme/.travis.yml b/vendor/github.com/proglottis/gpgme/.travis.yml
index 619e33721..619e33721 100644
--- a/vendor/github.com/mtrmac/gpgme/.travis.yml
+++ b/vendor/github.com/proglottis/gpgme/.travis.yml
diff --git a/vendor/github.com/mtrmac/gpgme/LICENSE b/vendor/github.com/proglottis/gpgme/LICENSE
index 06d4ab773..06d4ab773 100644
--- a/vendor/github.com/mtrmac/gpgme/LICENSE
+++ b/vendor/github.com/proglottis/gpgme/LICENSE
diff --git a/vendor/github.com/mtrmac/gpgme/README.md b/vendor/github.com/proglottis/gpgme/README.md
index 4770b82a8..4770b82a8 100644
--- a/vendor/github.com/mtrmac/gpgme/README.md
+++ b/vendor/github.com/proglottis/gpgme/README.md
diff --git a/vendor/github.com/mtrmac/gpgme/callbacks.go b/vendor/github.com/proglottis/gpgme/callbacks.go
index d1dc610d4..d1dc610d4 100644
--- a/vendor/github.com/mtrmac/gpgme/callbacks.go
+++ b/vendor/github.com/proglottis/gpgme/callbacks.go
diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/proglottis/gpgme/data.go
index eee32c032..eee32c032 100644
--- a/vendor/github.com/mtrmac/gpgme/data.go
+++ b/vendor/github.com/proglottis/gpgme/data.go
diff --git a/vendor/github.com/proglottis/gpgme/go.mod b/vendor/github.com/proglottis/gpgme/go.mod
new file mode 100644
index 000000000..5badc8e69
--- /dev/null
+++ b/vendor/github.com/proglottis/gpgme/go.mod
@@ -0,0 +1,3 @@
+module github.com/proglottis/gpgme
+
+go 1.11
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/proglottis/gpgme/go_gpgme.c
index 00da3ab30..00da3ab30 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c
+++ b/vendor/github.com/proglottis/gpgme/go_gpgme.c
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/proglottis/gpgme/go_gpgme.h
index d4826ab36..eb3a4ba88 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h
+++ b/vendor/github.com/proglottis/gpgme/go_gpgme.h
@@ -6,11 +6,6 @@
#include <gpgme.h>
-/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
-#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
-typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
-#endif
-
extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/proglottis/gpgme/gpgme.go
index c19b9aebc..9833057a6 100644
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
+++ b/vendor/github.com/proglottis/gpgme/gpgme.go
@@ -53,13 +53,13 @@ const (
type PinEntryMode int
-// const ( // Unavailable in 1.3.2
-// PinEntryDefault PinEntryMode = C.GPGME_PINENTRY_MODE_DEFAULT
-// PinEntryAsk PinEntryMode = C.GPGME_PINENTRY_MODE_ASK
-// PinEntryCancel PinEntryMode = C.GPGME_PINENTRY_MODE_CANCEL
-// PinEntryError PinEntryMode = C.GPGME_PINENTRY_MODE_ERROR
-// PinEntryLoopback PinEntryMode = C.GPGME_PINENTRY_MODE_LOOPBACK
-// )
+const (
+ PinEntryDefault PinEntryMode = C.GPGME_PINENTRY_MODE_DEFAULT
+ PinEntryAsk PinEntryMode = C.GPGME_PINENTRY_MODE_ASK
+ PinEntryCancel PinEntryMode = C.GPGME_PINENTRY_MODE_CANCEL
+ PinEntryError PinEntryMode = C.GPGME_PINENTRY_MODE_ERROR
+ PinEntryLoopback PinEntryMode = C.GPGME_PINENTRY_MODE_LOOPBACK
+)
type EncryptFlag uint
@@ -348,19 +348,17 @@ func (c *Context) KeyListMode() KeyListMode {
return res
}
-// Unavailable in 1.3.2:
-// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
-// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
-// runtime.KeepAlive(c)
-// return err
-// }
+func (c *Context) SetPinEntryMode(m PinEntryMode) error {
+ err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+ runtime.KeepAlive(c)
+ return err
+}
-// Unavailable in 1.3.2:
-// func (c *Context) PinEntryMode() PinEntryMode {
-// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
-// runtime.KeepAlive(c)
-// return res
-// }
+func (c *Context) PinEntryMode() PinEntryMode {
+ res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+ runtime.KeepAlive(c)
+ return res
+}
func (c *Context) SetCallback(callback Callback) error {
var err error
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/proglottis/gpgme/unset_agent_info.go
index 986aca59f..986aca59f 100644
--- a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
+++ b/vendor/github.com/proglottis/gpgme/unset_agent_info.go
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/proglottis/gpgme/unset_agent_info_windows.go
index 431ec86d3..431ec86d3 100644
--- a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
+++ b/vendor/github.com/proglottis/gpgme/unset_agent_info_windows.go
diff --git a/vendor/github.com/sylabs/sif/v2/LICENSE.md b/vendor/github.com/sylabs/sif/v2/LICENSE.md
new file mode 100644
index 000000000..30ea0e758
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/LICENSE.md
@@ -0,0 +1,29 @@
+# LICENSE
+
+Copyright (c) 2018-2021, Sylabs Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/arch.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/arch.go
new file mode 100644
index 000000000..d7acbb694
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/arch.go
@@ -0,0 +1,69 @@
+// Copyright (c) 2021, Sylabs Inc. All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+var (
+ hdrArchUnknown archType = [...]byte{'0', '0', '\x00'}
+ hdrArch386 archType = [...]byte{'0', '1', '\x00'}
+ hdrArchAMD64 archType = [...]byte{'0', '2', '\x00'}
+ hdrArchARM archType = [...]byte{'0', '3', '\x00'}
+ hdrArchARM64 archType = [...]byte{'0', '4', '\x00'}
+ hdrArchPPC64 archType = [...]byte{'0', '5', '\x00'}
+ hdrArchPPC64le archType = [...]byte{'0', '6', '\x00'}
+ hdrArchMIPS archType = [...]byte{'0', '7', '\x00'}
+ hdrArchMIPSle archType = [...]byte{'0', '8', '\x00'}
+ hdrArchMIPS64 archType = [...]byte{'0', '9', '\x00'}
+ hdrArchMIPS64le archType = [...]byte{'1', '0', '\x00'}
+ hdrArchS390x archType = [...]byte{'1', '1', '\x00'}
+)
+
+type archType [3]byte
+
+// getSIFArch returns the archType corresponding to go runtime arch.
+func getSIFArch(arch string) archType {
+ archMap := map[string]archType{
+ "386": hdrArch386,
+ "amd64": hdrArchAMD64,
+ "arm": hdrArchARM,
+ "arm64": hdrArchARM64,
+ "ppc64": hdrArchPPC64,
+ "ppc64le": hdrArchPPC64le,
+ "mips": hdrArchMIPS,
+ "mipsle": hdrArchMIPSle,
+ "mips64": hdrArchMIPS64,
+ "mips64le": hdrArchMIPS64le,
+ "s390x": hdrArchS390x,
+ }
+
+ t, ok := archMap[arch]
+ if !ok {
+ return hdrArchUnknown
+ }
+ return t
+}
+
+// GoArch returns the go runtime arch corresponding to t.
+func (t archType) GoArch() string {
+ archMap := map[archType]string{
+ hdrArch386: "386",
+ hdrArchAMD64: "amd64",
+ hdrArchARM: "arm",
+ hdrArchARM64: "arm64",
+ hdrArchPPC64: "ppc64",
+ hdrArchPPC64le: "ppc64le",
+ hdrArchMIPS: "mips",
+ hdrArchMIPSle: "mipsle",
+ hdrArchMIPS64: "mips64",
+ hdrArchMIPS64le: "mips64le",
+ hdrArchS390x: "s390x",
+ }
+
+ arch, ok := archMap[t]
+ if !ok {
+ arch = "unknown"
+ }
+ return arch
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/buffer.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/buffer.go
new file mode 100644
index 000000000..d706fb1a5
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/buffer.go
@@ -0,0 +1,103 @@
+// Copyright (c) 2021, Sylabs Inc. All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "errors"
+ "io"
+)
+
+// A Buffer is a variable-sized buffer of bytes that implements the sif.ReadWriter interface. The
+// zero value for Buffer is an empty buffer ready to use.
+type Buffer struct {
+ buf []byte
+ pos int64
+}
+
+// NewBuffer creates and initializes a new Buffer using buf as its initial contents.
+func NewBuffer(buf []byte) *Buffer {
+ return &Buffer{buf: buf}
+}
+
+var errNegativeOffset = errors.New("negative offset")
+
+// ReadAt implements the io.ReaderAt interface.
+func (b *Buffer) ReadAt(p []byte, off int64) (n int, err error) {
+ if off < 0 {
+ return 0, errNegativeOffset
+ }
+
+ if off >= int64(len(b.buf)) {
+ return 0, io.EOF
+ }
+
+ n = copy(p, b.buf[off:])
+ if n < len(p) {
+ err = io.EOF
+ }
+ return n, err
+}
+
+var errNegativePosition = errors.New("negative position")
+
+// Write implements the io.Writer interface.
+func (b *Buffer) Write(p []byte) (n int, err error) {
+ if b.pos < 0 {
+ return 0, errNegativePosition
+ }
+
+ if have, need := int64(len(b.buf))-b.pos, int64(len(p)); have < need {
+ b.buf = append(b.buf, make([]byte, need-have)...)
+ }
+
+ n = copy(b.buf[b.pos:], p)
+ b.pos += int64(n)
+ return n, nil
+}
+
+var errInvalidWhence = errors.New("invalid whence")
+
+// Seek implements the io.Seeker interface.
+func (b *Buffer) Seek(offset int64, whence int) (int64, error) {
+ var abs int64
+
+ switch whence {
+ case io.SeekStart:
+ abs = offset
+ case io.SeekCurrent:
+ abs = b.pos + offset
+ case io.SeekEnd:
+ abs = int64(len(b.buf)) + offset
+ default:
+ return 0, errInvalidWhence
+ }
+
+ if abs < 0 {
+ return 0, errNegativePosition
+ }
+
+ b.pos = abs
+ return abs, nil
+}
+
+var errTruncateRange = errors.New("truncation out of range")
+
+// Truncate discards all but the first n bytes from the buffer.
+func (b *Buffer) Truncate(n int64) error {
+ if n < 0 || n > int64(len(b.buf)) {
+ return errTruncateRange
+ }
+
+ b.buf = b.buf[:n]
+ return nil
+}
+
+// Bytes returns the contents of the buffer. The slice is valid for use only until the next buffer
+// modification (that is, only until the next call to a method like ReadAt, Write, or Truncate).
+func (b *Buffer) Bytes() []byte { return b.buf }
+
+// Len returns the number of bytes in the buffer.
+func (b *Buffer) Len() int64 { return int64(len(b.buf)) }
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/create.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/create.go
new file mode 100644
index 000000000..e65bdb747
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/create.go
@@ -0,0 +1,680 @@
+// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved.
+// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+// Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "time"
+
+ "github.com/google/uuid"
+)
+
+// nextAligned finds the next offset that satisfies alignment.
+func nextAligned(offset int64, alignment int) int64 {
+ align64 := uint64(alignment)
+ offset64 := uint64(offset)
+
+ if align64 != 0 && offset64%align64 != 0 {
+ offset64 = (offset64 & ^(align64 - 1)) + align64
+ }
+
+ return int64(offset64)
+}
+
+// writeDataObjectAt writes the data object described by di to ws, using time t, recording details
+// in d. The object is written at the first position that satisfies the alignment requirements
+// described by di following offsetUnaligned.
+func writeDataObjectAt(ws io.WriteSeeker, offsetUnaligned int64, di DescriptorInput, t time.Time, d *rawDescriptor) error { //nolint:lll
+ offset, err := ws.Seek(nextAligned(offsetUnaligned, di.opts.alignment), io.SeekStart)
+ if err != nil {
+ return err
+ }
+
+ n, err := io.Copy(ws, di.r)
+ if err != nil {
+ return err
+ }
+
+ if err := di.fillDescriptor(t, d); err != nil {
+ return err
+ }
+ d.Used = true
+ d.Offset = offset
+ d.Size = n
+ d.SizeWithPadding = offset - offsetUnaligned + n
+
+ return nil
+}
+
+var (
+ errInsufficientCapacity = errors.New("insufficient descriptor capacity to add data object(s) to image")
+ errPrimaryPartition = errors.New("image already contains a primary partition")
+)
+
+// writeDataObject writes the data object described by di to f, using time t, recording details in
+// the descriptor at index i.
+func (f *FileImage) writeDataObject(i int, di DescriptorInput, t time.Time) error {
+ if i >= len(f.rds) {
+ return errInsufficientCapacity
+ }
+
+ // If this is a primary partition, verify there isn't another primary partition, and update the
+ // architecture in the global header.
+ if p, ok := di.opts.extra.(partition); ok && p.Parttype == PartPrimSys {
+ if ds, err := f.GetDescriptors(WithPartitionType(PartPrimSys)); err == nil && len(ds) > 0 {
+ return errPrimaryPartition
+ }
+
+ f.h.Arch = p.Arch
+ }
+
+ d := &f.rds[i]
+ d.ID = uint32(i) + 1
+
+ if err := writeDataObjectAt(f.rw, f.h.DataOffset+f.h.DataSize, di, t, d); err != nil {
+ return err
+ }
+
+ // Update minimum object ID map.
+ if minID, ok := f.minIDs[d.GroupID]; !ok || d.ID < minID {
+ f.minIDs[d.GroupID] = d.ID
+ }
+
+ f.h.DescriptorsFree--
+ f.h.DataSize += d.SizeWithPadding
+
+ return nil
+}
+
+// writeDescriptors writes the descriptors in f to backing storage.
+func (f *FileImage) writeDescriptors() error {
+ if _, err := f.rw.Seek(f.h.DescriptorsOffset, io.SeekStart); err != nil {
+ return err
+ }
+
+ return binary.Write(f.rw, binary.LittleEndian, f.rds)
+}
+
+// writeHeader writes the the global header in f to backing storage.
+func (f *FileImage) writeHeader() error {
+ if _, err := f.rw.Seek(0, io.SeekStart); err != nil {
+ return err
+ }
+
+ return binary.Write(f.rw, binary.LittleEndian, f.h)
+}
+
+// createOpts accumulates container creation options.
+type createOpts struct {
+ launchScript [hdrLaunchLen]byte
+ id uuid.UUID
+ descriptorsOffset int64
+ descriptorCapacity int64
+ dis []DescriptorInput
+ t time.Time
+ closeOnUnload bool
+}
+
+// CreateOpt are used to specify container creation options.
+type CreateOpt func(*createOpts) error
+
+var errLaunchScriptLen = errors.New("launch script too large")
+
+// OptCreateWithLaunchScript specifies s as the launch script.
+func OptCreateWithLaunchScript(s string) CreateOpt {
+ return func(co *createOpts) error {
+ b := []byte(s)
+
+ if len(b) >= len(co.launchScript) {
+ return errLaunchScriptLen
+ }
+
+ copy(co.launchScript[:], b)
+
+ return nil
+ }
+}
+
+// OptCreateDeterministic sets header/descriptor fields to values that support deterministic
+// creation of images.
+func OptCreateDeterministic() CreateOpt {
+ return func(co *createOpts) error {
+ co.id = uuid.Nil
+ co.t = time.Time{}
+ return nil
+ }
+}
+
+// OptCreateWithID specifies id as the unique ID.
+func OptCreateWithID(id string) CreateOpt {
+ return func(co *createOpts) error {
+ id, err := uuid.Parse(id)
+ co.id = id
+ return err
+ }
+}
+
+// OptCreateWithDescriptorCapacity specifies that the created image should have the capacity for a
+// maximum of n descriptors.
+func OptCreateWithDescriptorCapacity(n int64) CreateOpt {
+ return func(co *createOpts) error {
+ co.descriptorCapacity = n
+ return nil
+ }
+}
+
+// OptCreateWithDescriptors appends dis to the list of descriptors.
+func OptCreateWithDescriptors(dis ...DescriptorInput) CreateOpt {
+ return func(co *createOpts) error {
+ co.dis = append(co.dis, dis...)
+ return nil
+ }
+}
+
+// OptCreateWithTime specifies t as the image creation time.
+func OptCreateWithTime(t time.Time) CreateOpt {
+ return func(co *createOpts) error {
+ co.t = t
+ return nil
+ }
+}
+
+// OptCreateWithCloseOnUnload specifies whether the ReadWriter should be closed by UnloadContainer.
+// By default, the ReadWriter will be closed if it implements the io.Closer interface.
+func OptCreateWithCloseOnUnload(b bool) CreateOpt {
+ return func(co *createOpts) error {
+ co.closeOnUnload = b
+ return nil
+ }
+}
+
+// createContainer creates a new SIF container file in rw, according to opts.
+func createContainer(rw ReadWriter, co createOpts) (*FileImage, error) {
+ rds := make([]rawDescriptor, co.descriptorCapacity)
+ rdsSize := int64(binary.Size(rds))
+
+ h := header{
+ LaunchScript: co.launchScript,
+ Magic: hdrMagic,
+ Version: CurrentVersion.bytes(),
+ Arch: hdrArchUnknown,
+ ID: co.id,
+ CreatedAt: co.t.Unix(),
+ ModifiedAt: co.t.Unix(),
+ DescriptorsFree: co.descriptorCapacity,
+ DescriptorsTotal: co.descriptorCapacity,
+ DescriptorsOffset: co.descriptorsOffset,
+ DescriptorsSize: rdsSize,
+ DataOffset: co.descriptorsOffset + rdsSize,
+ }
+
+ f := &FileImage{
+ rw: rw,
+ h: h,
+ rds: rds,
+ minIDs: make(map[uint32]uint32),
+ }
+
+ for i, di := range co.dis {
+ if err := f.writeDataObject(i, di, co.t); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := f.writeDescriptors(); err != nil {
+ return nil, err
+ }
+
+ if err := f.writeHeader(); err != nil {
+ return nil, err
+ }
+
+ return f, nil
+}
+
+// CreateContainer creates a new SIF container in rw, according to opts. One or more data objects
+// can optionally be specified using OptCreateWithDescriptors.
+//
+// On success, a FileImage is returned. The caller must call UnloadContainer to ensure resources
+// are released. By default, UnloadContainer will close rw if it implements the io.Closer
+// interface. To change this behavior, consider using OptCreateWithCloseOnUnload.
+//
+// By default, the image ID is set to a randomly generated value. To override this, consider using
+// OptCreateDeterministic or OptCreateWithID.
+//
+// By default, the image creation time is set to time.Now(). To override this, consider using
+// OptCreateDeterministic or OptCreateWithTime.
+//
+// By default, the image will support a maximum of 48 descriptors. To change this, consider using
+// OptCreateWithDescriptorCapacity.
+//
+// A launch script can optionally be set using OptCreateWithLaunchScript.
+func CreateContainer(rw ReadWriter, opts ...CreateOpt) (*FileImage, error) {
+ id, err := uuid.NewRandom()
+ if err != nil {
+ return nil, err
+ }
+
+ co := createOpts{
+ id: id,
+ descriptorsOffset: 4096,
+ descriptorCapacity: 48,
+ t: time.Now(),
+ closeOnUnload: true,
+ }
+
+ for _, opt := range opts {
+ if err := opt(&co); err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+ }
+
+ f, err := createContainer(rw, co)
+ if err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ f.closeOnUnload = co.closeOnUnload
+ return f, nil
+}
+
+// CreateContainerAtPath creates a new SIF container file at path, according to opts. One or more
+// data objects can optionally be specified using OptCreateWithDescriptors.
+//
+// On success, a FileImage is returned. The caller must call UnloadContainer to ensure resources
+// are released.
+//
+// By default, the image ID is set to a randomly generated value. To override this, consider using
+// OptCreateDeterministic or OptCreateWithID.
+//
+// By default, the image creation time is set to time.Now(). To override this, consider using
+// OptCreateDeterministic or OptCreateWithTime.
+//
+// By default, the image will support a maximum of 48 descriptors. To change this, consider using
+// OptCreateWithDescriptorCapacity.
+//
+// A launch script can optionally be set using OptCreateWithLaunchScript.
+func CreateContainerAtPath(path string, opts ...CreateOpt) (*FileImage, error) {
+ fp, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o755)
+ if err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ f, err := CreateContainer(fp, opts...)
+ if err != nil {
+ fp.Close()
+ os.Remove(fp.Name())
+
+ return nil, err
+ }
+
+ f.closeOnUnload = true
+ return f, nil
+}
+
+func zeroData(fimg *FileImage, descr *rawDescriptor) error {
+ // first, move to data object offset
+ if _, err := fimg.rw.Seek(descr.Offset, io.SeekStart); err != nil {
+ return err
+ }
+
+ var zero [4096]byte
+ n := descr.Size
+ upbound := int64(4096)
+ for {
+ if n < 4096 {
+ upbound = n
+ }
+
+ if _, err := fimg.rw.Write(zero[:upbound]); err != nil {
+ return err
+ }
+ n -= 4096
+ if n <= 0 {
+ break
+ }
+ }
+
+ return nil
+}
+
+func resetDescriptor(fimg *FileImage, index int) error {
+ // If we remove the primary partition, set the global header Arch field to HdrArchUnknown
+ // to indicate that the SIF file doesn't include a primary partition and no dependency
+ // on any architecture exists.
+ if fimg.rds[index].isPartitionOfType(PartPrimSys) {
+ fimg.h.Arch = hdrArchUnknown
+ }
+
+ offset := fimg.h.DescriptorsOffset + int64(index)*int64(binary.Size(fimg.rds[0]))
+
+ // first, move to descriptor offset
+ if _, err := fimg.rw.Seek(offset, io.SeekStart); err != nil {
+ return err
+ }
+
+ var emptyDesc rawDescriptor
+ return binary.Write(fimg.rw, binary.LittleEndian, emptyDesc)
+}
+
+// addOpts accumulates object add options.
+type addOpts struct {
+ t time.Time
+}
+
+// AddOpt are used to specify object add options.
+type AddOpt func(*addOpts) error
+
+// OptAddDeterministic sets header/descriptor fields to values that support deterministic
+// modification of images.
+func OptAddDeterministic() AddOpt {
+ return func(ao *addOpts) error {
+ ao.t = time.Time{}
+ return nil
+ }
+}
+
+// OptAddWithTime specifies t as the image modification time.
+func OptAddWithTime(t time.Time) AddOpt {
+ return func(ao *addOpts) error {
+ ao.t = t
+ return nil
+ }
+}
+
+// AddObject adds a new data object and its descriptor into the specified SIF file.
+//
+// By default, the image modification time is set to the current time. To override this, consider
+// using OptAddDeterministic or OptAddWithTime.
+func (f *FileImage) AddObject(di DescriptorInput, opts ...AddOpt) error {
+ ao := addOpts{
+ t: time.Now(),
+ }
+
+ for _, opt := range opts {
+ if err := opt(&ao); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+
+ // Find an unused descriptor.
+ i := 0
+ for _, rd := range f.rds {
+ if !rd.Used {
+ break
+ }
+ i++
+ }
+
+ if err := f.writeDataObject(i, di, ao.t); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ if err := f.writeDescriptors(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ f.h.ModifiedAt = ao.t.Unix()
+
+ if err := f.writeHeader(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ return nil
+}
+
+// isLast return true if the data object associated with d is the last in f.
+func (f *FileImage) isLast(d *rawDescriptor) bool {
+ isLast := true
+
+ end := d.Offset + d.Size
+ f.WithDescriptors(func(d Descriptor) bool {
+ isLast = d.Offset()+d.Size() <= end
+ return !isLast
+ })
+
+ return isLast
+}
+
+// truncateAt truncates f at the start of the padded data object described by d.
+func (f *FileImage) truncateAt(d *rawDescriptor) error {
+ start := d.Offset + d.Size - d.SizeWithPadding
+
+ if err := f.rw.Truncate(start); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// deleteOpts accumulates object deletion options.
+type deleteOpts struct {
+ zero bool
+ compact bool
+ t time.Time
+}
+
+// DeleteOpt are used to specify object deletion options.
+type DeleteOpt func(*deleteOpts) error
+
+// OptDeleteZero specifies whether the deleted object should be zeroed.
+func OptDeleteZero(b bool) DeleteOpt {
+ return func(do *deleteOpts) error {
+ do.zero = b
+ return nil
+ }
+}
+
+// OptDeleteCompact specifies whether the image should be compacted following object deletion.
+func OptDeleteCompact(b bool) DeleteOpt {
+ return func(do *deleteOpts) error {
+ do.compact = b
+ return nil
+ }
+}
+
+// OptDeleteDeterministic sets header/descriptor fields to values that support deterministic
+// modification of images.
+func OptDeleteDeterministic() DeleteOpt {
+ return func(do *deleteOpts) error {
+ do.t = time.Time{}
+ return nil
+ }
+}
+
+// OptDeleteWithTime specifies t as the image modification time.
+func OptDeleteWithTime(t time.Time) DeleteOpt {
+ return func(do *deleteOpts) error {
+ do.t = t
+ return nil
+ }
+}
+
+var errCompactNotImplemented = errors.New("compact not implemented for non-last object")
+
+// DeleteObject deletes the data object with id, according to opts.
+//
+// To zero the data region of the deleted object, use OptDeleteZero. To compact the file following
+// object deletion, use OptDeleteCompact.
+//
+// By default, the image modification time is set to time.Now(). To override this, consider using
+// OptDeleteDeterministic or OptDeleteWithTime.
+func (f *FileImage) DeleteObject(id uint32, opts ...DeleteOpt) error {
+ do := deleteOpts{
+ t: time.Now(),
+ }
+
+ for _, opt := range opts {
+ if err := opt(&do); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+
+ d, err := f.getDescriptor(WithID(id))
+ if err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ if do.compact && !f.isLast(d) {
+ return fmt.Errorf("%w", errCompactNotImplemented)
+ }
+
+ if do.zero {
+ if err := zeroData(f, d); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+
+ if do.compact {
+ if err := f.truncateAt(d); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ f.h.DataSize -= d.SizeWithPadding
+ }
+
+ f.h.DescriptorsFree++
+ f.h.ModifiedAt = do.t.Unix()
+
+ index := 0
+ for i, od := range f.rds {
+ if od.ID == id {
+ index = i
+ break
+ }
+ }
+
+ if err := resetDescriptor(f, index); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ if err := f.writeHeader(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ return nil
+}
+
+// setOpts accumulates object set options.
+type setOpts struct {
+ t time.Time
+}
+
+// SetOpt are used to specify object set options.
+type SetOpt func(*setOpts) error
+
+// OptSetDeterministic sets header/descriptor fields to values that support deterministic
+// modification of images.
+func OptSetDeterministic() SetOpt {
+ return func(so *setOpts) error {
+ so.t = time.Time{}
+ return nil
+ }
+}
+
+// OptSetWithTime specifies t as the image/object modification time.
+func OptSetWithTime(t time.Time) SetOpt {
+ return func(so *setOpts) error {
+ so.t = t
+ return nil
+ }
+}
+
+var (
+ errNotPartition = errors.New("data object not a partition")
+ errNotSystem = errors.New("data object not a system partition")
+)
+
+// SetPrimPart sets the specified system partition to be the primary one.
+//
+// By default, the image/object modification times are set to time.Now(). To override this,
+// consider using OptSetDeterministic or OptSetWithTime.
+func (f *FileImage) SetPrimPart(id uint32, opts ...SetOpt) error {
+ so := setOpts{
+ t: time.Now(),
+ }
+
+ for _, opt := range opts {
+ if err := opt(&so); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+
+ descr, err := f.getDescriptor(WithID(id))
+ if err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ if descr.DataType != DataPartition {
+ return fmt.Errorf("%w", errNotPartition)
+ }
+
+ fs, pt, arch, err := descr.getPartitionMetadata()
+ if err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ // if already primary system partition, nothing to do
+ if pt == PartPrimSys {
+ return nil
+ }
+
+ if pt != PartSystem {
+ return fmt.Errorf("%w", errNotSystem)
+ }
+
+ olddescr, err := f.getDescriptor(WithPartitionType(PartPrimSys))
+ if err != nil && !errors.Is(err, ErrObjectNotFound) {
+ return fmt.Errorf("%w", err)
+ }
+
+ f.h.Arch = getSIFArch(arch)
+
+ extra := partition{
+ Fstype: fs,
+ Parttype: PartPrimSys,
+ }
+ copy(extra.Arch[:], arch)
+
+ if err := descr.setExtra(extra); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ if olddescr != nil {
+ oldfs, _, oldarch, err := olddescr.getPartitionMetadata()
+ if err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ oldextra := partition{
+ Fstype: oldfs,
+ Parttype: PartSystem,
+ Arch: getSIFArch(oldarch),
+ }
+
+ if err := olddescr.setExtra(oldextra); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+
+ if err := f.writeDescriptors(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ f.h.ModifiedAt = so.t.Unix()
+
+ if err := f.writeHeader(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor.go
new file mode 100644
index 000000000..da7a6a7c7
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor.go
@@ -0,0 +1,267 @@
+// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved.
+// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+// Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "bytes"
+ "crypto"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+ "time"
+)
+
+// rawDescriptor represents an on-disk object descriptor.
+type rawDescriptor struct {
+ DataType DataType
+ Used bool
+ ID uint32
+ GroupID uint32
+ LinkedID uint32
+ Offset int64
+ Size int64
+ SizeWithPadding int64
+
+ CreatedAt int64
+ ModifiedAt int64
+ UID int64 // Deprecated: UID exists for historical compatibility and should not be used.
+ GID int64 // Deprecated: GID exists for historical compatibility and should not be used.
+ Name [descrNameLen]byte
+ Extra [descrMaxPrivLen]byte
+}
+
+// partition represents the SIF partition data object descriptor.
+type partition struct {
+ Fstype FSType
+ Parttype PartType
+ Arch archType
+}
+
+// signature represents the SIF signature data object descriptor.
+type signature struct {
+ Hashtype hashType
+ Entity [descrEntityLen]byte
+}
+
+// cryptoMessage represents the SIF crypto message object descriptor.
+type cryptoMessage struct {
+ Formattype FormatType
+ Messagetype MessageType
+}
+
+var errNameTooLarge = errors.New("name value too large")
+
+// setName encodes name into the name field of d.
+func (d *rawDescriptor) setName(name string) error {
+ if len(name) > len(d.Name) {
+ return errNameTooLarge
+ }
+
+ for i := copy(d.Name[:], name); i < len(d.Name); i++ {
+ d.Name[i] = 0
+ }
+
+ return nil
+}
+
+var errExtraTooLarge = errors.New("extra value too large")
+
+// setExtra encodes v into the extra field of d.
+func (d *rawDescriptor) setExtra(v interface{}) error {
+ if v == nil {
+ return nil
+ }
+
+ if binary.Size(v) > len(d.Extra) {
+ return errExtraTooLarge
+ }
+
+ b := new(bytes.Buffer)
+ if err := binary.Write(b, binary.LittleEndian, v); err != nil {
+ return err
+ }
+
+ for i := copy(d.Extra[:], b.Bytes()); i < len(d.Extra); i++ {
+ d.Extra[i] = 0
+ }
+
+ return nil
+}
+
+// getPartitionMetadata gets metadata for a partition data object.
+func (d rawDescriptor) getPartitionMetadata() (fs FSType, pt PartType, arch string, err error) {
+ if got, want := d.DataType, DataPartition; got != want {
+ return 0, 0, "", &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ var p partition
+
+ b := bytes.NewReader(d.Extra[:])
+ if err := binary.Read(b, binary.LittleEndian, &p); err != nil {
+ return 0, 0, "", fmt.Errorf("%w", err)
+ }
+
+ return p.Fstype, p.Parttype, p.Arch.GoArch(), nil
+}
+
+// isPartitionOfType returns true if d is a partition data object of type pt.
+func (d rawDescriptor) isPartitionOfType(pt PartType) bool {
+ _, t, _, err := d.getPartitionMetadata()
+ if err != nil {
+ return false
+ }
+ return t == pt
+}
+
+// Descriptor represents the SIF descriptor type.
+type Descriptor struct {
+ r io.ReaderAt // Backing storage.
+
+ raw rawDescriptor // Raw descriptor from image.
+
+ relativeID uint32 // ID relative to minimum ID of object group.
+}
+
+// DataType returns the type of data object.
+func (d Descriptor) DataType() DataType { return d.raw.DataType }
+
+// ID returns the data object ID of d.
+func (d Descriptor) ID() uint32 { return d.raw.ID }
+
+// GroupID returns the data object group ID of d, or zero if d is not part of a data object
+// group.
+func (d Descriptor) GroupID() uint32 { return d.raw.GroupID &^ descrGroupMask }
+
+// LinkedID returns the object/group ID d is linked to, or zero if d does not contain a linked
+// ID. If isGroup is true, the returned id is an object group ID. Otherwise, the returned id is a
+// data object ID.
+func (d Descriptor) LinkedID() (id uint32, isGroup bool) {
+ return d.raw.LinkedID &^ descrGroupMask, d.raw.LinkedID&descrGroupMask == descrGroupMask
+}
+
+// Offset returns the offset of the data object.
+func (d Descriptor) Offset() int64 { return d.raw.Offset }
+
+// Size returns the data object size.
+func (d Descriptor) Size() int64 { return d.raw.Size }
+
+// CreatedAt returns the creation time of the data object.
+func (d Descriptor) CreatedAt() time.Time { return time.Unix(d.raw.CreatedAt, 0) }
+
+// ModifiedAt returns the modification time of the data object.
+func (d Descriptor) ModifiedAt() time.Time { return time.Unix(d.raw.ModifiedAt, 0) }
+
+// Name returns the name of the data object.
+func (d Descriptor) Name() string { return strings.TrimRight(string(d.raw.Name[:]), "\000") }
+
+// PartitionMetadata gets metadata for a partition data object.
+func (d Descriptor) PartitionMetadata() (fs FSType, pt PartType, arch string, err error) {
+ return d.raw.getPartitionMetadata()
+}
+
+var errHashUnsupported = errors.New("hash algorithm unsupported")
+
+// getHashType converts ht into a crypto.Hash.
+func getHashType(ht hashType) (crypto.Hash, error) {
+ switch ht {
+ case hashSHA256:
+ return crypto.SHA256, nil
+ case hashSHA384:
+ return crypto.SHA384, nil
+ case hashSHA512:
+ return crypto.SHA512, nil
+ case hashBLAKE2S:
+ return crypto.BLAKE2s_256, nil
+ case hashBLAKE2B:
+ return crypto.BLAKE2b_256, nil
+ }
+ return 0, errHashUnsupported
+}
+
+// SignatureMetadata gets metadata for a signature data object.
+func (d Descriptor) SignatureMetadata() (ht crypto.Hash, fp []byte, err error) {
+ if got, want := d.raw.DataType, DataSignature; got != want {
+ return ht, fp, &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ var s signature
+
+ b := bytes.NewReader(d.raw.Extra[:])
+ if err := binary.Read(b, binary.LittleEndian, &s); err != nil {
+ return ht, fp, fmt.Errorf("%w", err)
+ }
+
+ if ht, err = getHashType(s.Hashtype); err != nil {
+ return ht, fp, fmt.Errorf("%w", err)
+ }
+
+ fp = make([]byte, 20)
+ copy(fp, s.Entity[:])
+
+ return ht, fp, nil
+}
+
+// CryptoMessageMetadata gets metadata for a crypto message data object.
+func (d Descriptor) CryptoMessageMetadata() (FormatType, MessageType, error) {
+ if got, want := d.raw.DataType, DataCryptoMessage; got != want {
+ return 0, 0, &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ var m cryptoMessage
+
+ b := bytes.NewReader(d.raw.Extra[:])
+ if err := binary.Read(b, binary.LittleEndian, &m); err != nil {
+ return 0, 0, fmt.Errorf("%w", err)
+ }
+
+ return m.Formattype, m.Messagetype, nil
+}
+
+// GetData returns the data object associated with descriptor d.
+func (d Descriptor) GetData() ([]byte, error) {
+ b := make([]byte, d.raw.Size)
+ if _, err := io.ReadFull(d.GetReader(), b); err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+// GetReader returns a io.Reader that reads the data object associated with descriptor d.
+func (d Descriptor) GetReader() io.Reader {
+ return io.NewSectionReader(d.r, d.raw.Offset, d.raw.Size)
+}
+
+// GetIntegrityReader returns an io.Reader that reads the integrity-protected fields from d.
+func (d Descriptor) GetIntegrityReader() io.Reader {
+ fields := []interface{}{
+ d.raw.DataType,
+ d.raw.Used,
+ d.relativeID,
+ d.raw.LinkedID,
+ d.raw.Size,
+ d.raw.CreatedAt,
+ d.raw.UID,
+ d.raw.GID,
+ }
+
+ // Encode endian-sensitive fields.
+ data := bytes.Buffer{}
+ for _, f := range fields {
+ if err := binary.Write(&data, binary.LittleEndian, f); err != nil {
+ panic(err) // (*bytes.Buffer).Write() is documented as always returning a nil error.
+ }
+ }
+
+ return io.MultiReader(
+ &data,
+ bytes.NewReader(d.raw.Name[:]),
+ bytes.NewReader(d.raw.Extra[:]),
+ )
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor_input.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor_input.go
new file mode 100644
index 000000000..c55cf51f9
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/descriptor_input.go
@@ -0,0 +1,300 @@
+// Copyright (c) 2021, Sylabs Inc. All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "crypto"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "time"
+)
+
+// descriptorOpts accumulates data object options.
+type descriptorOpts struct {
+ groupID uint32
+ linkID uint32
+ alignment int
+ name string
+ extra interface{}
+ t time.Time
+}
+
+// DescriptorInputOpt are used to specify data object options.
+type DescriptorInputOpt func(DataType, *descriptorOpts) error
+
+// OptNoGroup specifies the data object is not contained within a data object group.
+func OptNoGroup() DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ opts.groupID = 0
+ return nil
+ }
+}
+
+// OptGroupID specifies groupID as data object group ID.
+func OptGroupID(groupID uint32) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ if groupID == 0 {
+ return ErrInvalidGroupID
+ }
+ opts.groupID = groupID
+ return nil
+ }
+}
+
+// OptLinkedID specifies that the data object is linked to the data object with the specified ID.
+func OptLinkedID(id uint32) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ if id == 0 {
+ return ErrInvalidObjectID
+ }
+ opts.linkID = id
+ return nil
+ }
+}
+
+// OptLinkedGroupID specifies that the data object is linked to the data object group with the
+// specified groupID.
+func OptLinkedGroupID(groupID uint32) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ if groupID == 0 {
+ return ErrInvalidGroupID
+ }
+ opts.linkID = groupID | descrGroupMask
+ return nil
+ }
+}
+
+// OptObjectAlignment specifies n as the data alignment requirement.
+func OptObjectAlignment(n int) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ opts.alignment = n
+ return nil
+ }
+}
+
+// OptObjectName specifies name as the data object name.
+func OptObjectName(name string) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ opts.name = name
+ return nil
+ }
+}
+
+// OptObjectTime specifies t as the data object creation time.
+func OptObjectTime(t time.Time) DescriptorInputOpt {
+ return func(_ DataType, opts *descriptorOpts) error {
+ opts.t = t
+ return nil
+ }
+}
+
+type unexpectedDataTypeError struct {
+ got DataType
+ want []DataType
+}
+
+func (e *unexpectedDataTypeError) Error() string {
+ return fmt.Sprintf("unexpected data type %v, expected one of: %v", e.got, e.want)
+}
+
+func (e *unexpectedDataTypeError) Is(target error) bool {
+ //nolint:errorlint // don't compare wrapped errors in Is()
+ t, ok := target.(*unexpectedDataTypeError)
+ if !ok {
+ return false
+ }
+
+ if len(t.want) > 0 {
+ // Use a map to check that the "want" errors in e and t contain the same values, ignoring
+ // any ordering differences.
+ acc := make(map[DataType]int, len(t.want))
+
+ // Increment counter for each data type in e.
+ for _, dt := range e.want {
+ if _, ok := acc[dt]; !ok {
+ acc[dt] = 0
+ }
+ acc[dt]++
+ }
+
+ // Decrement counter for each data type in e.
+ for _, dt := range t.want {
+ if _, ok := acc[dt]; !ok {
+ return false
+ }
+ acc[dt]--
+ }
+
+ // If the "want" errors in e and t are equivalent, all counters should be zero.
+ for _, n := range acc {
+ if n != 0 {
+ return false
+ }
+ }
+ }
+
+ return (e.got == t.got || t.got == 0)
+}
+
+// OptCryptoMessageMetadata sets metadata for a crypto message data object. The format type is set
+// to ft, and the message type is set to mt.
+//
+// If this option is applied to a data object with an incompatible type, an error is returned.
+func OptCryptoMessageMetadata(ft FormatType, mt MessageType) DescriptorInputOpt {
+ return func(t DataType, opts *descriptorOpts) error {
+ if got, want := t, DataCryptoMessage; got != want {
+ return &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ m := cryptoMessage{
+ Formattype: ft,
+ Messagetype: mt,
+ }
+
+ opts.extra = m
+ return nil
+ }
+}
+
+var errUnknownArchitcture = errors.New("unknown architecture")
+
+// OptPartitionMetadata sets metadata for a partition data object. The filesystem type is set to
+// fs, the partition type is set to pt, and the CPU architecture is set to arch. The value of arch
+// should be the architecture as represented by the Go runtime.
+//
+// If this option is applied to a data object with an incompatible type, an error is returned.
+func OptPartitionMetadata(fs FSType, pt PartType, arch string) DescriptorInputOpt {
+ return func(t DataType, opts *descriptorOpts) error {
+ if got, want := t, DataPartition; got != want {
+ return &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ sifarch := getSIFArch(arch)
+ if sifarch == hdrArchUnknown {
+ return fmt.Errorf("%w: %v", errUnknownArchitcture, arch)
+ }
+
+ p := partition{
+ Fstype: fs,
+ Parttype: pt,
+ Arch: sifarch,
+ }
+
+ opts.extra = p
+ return nil
+ }
+}
+
+// sifHashType converts h into a HashType.
+func sifHashType(h crypto.Hash) hashType {
+ switch h {
+ case crypto.SHA256:
+ return hashSHA256
+ case crypto.SHA384:
+ return hashSHA384
+ case crypto.SHA512:
+ return hashSHA512
+ case crypto.BLAKE2s_256:
+ return hashBLAKE2S
+ case crypto.BLAKE2b_256:
+ return hashBLAKE2B
+ }
+ return 0
+}
+
+// OptSignatureMetadata sets metadata for a signature data object. The hash type is set to ht, and
+// the signing entity fingerprint is set to fp.
+//
+// If this option is applied to a data object with an incompatible type, an error is returned.
+func OptSignatureMetadata(ht crypto.Hash, fp []byte) DescriptorInputOpt {
+ return func(t DataType, opts *descriptorOpts) error {
+ if got, want := t, DataSignature; got != want {
+ return &unexpectedDataTypeError{got, []DataType{want}}
+ }
+
+ s := signature{
+ Hashtype: sifHashType(ht),
+ }
+ copy(s.Entity[:], fp)
+
+ opts.extra = s
+ return nil
+ }
+}
+
+// DescriptorInput describes a new data object.
+type DescriptorInput struct {
+ dt DataType
+ r io.Reader
+ opts descriptorOpts
+}
+
+// DefaultObjectGroup is the default group that data objects are placed in.
+const DefaultObjectGroup = 1
+
+// NewDescriptorInput returns a DescriptorInput representing a data object of type t, with contents
+// read from r, configured according to opts.
+//
+// It is possible (and often necessary) to store additional metadata related to certain types of
+// data objects. Consider supplying options such as OptCryptoMessageMetadata, OptPartitionMetadata,
+// and OptSignatureMetadata for this purpose.
+//
+// By default, the data object will be placed in the default data object group (1). To override
+// this behavior, use OptNoGroup or OptGroupID. To link this data object, use OptLinkedID or
+// OptLinkedGroupID.
+//
+// By default, the data object will be aligned according to the system's memory page size. To
+// override this behavior, consider using OptObjectAlignment.
+//
+// By default, no name is set for data object. To set a name, use OptObjectName.
+//
+// When creating a new image, data object creation/modification times are set to the image creation
+// time. When modifying an existing image, the data object creation/modification time is set to the
+// image modification time. To override this behavior, consider using OptObjectTime.
+func NewDescriptorInput(t DataType, r io.Reader, opts ...DescriptorInputOpt) (DescriptorInput, error) {
+ dopts := descriptorOpts{
+ groupID: DefaultObjectGroup,
+ alignment: os.Getpagesize(),
+ }
+
+ for _, opt := range opts {
+ if err := opt(t, &dopts); err != nil {
+ return DescriptorInput{}, fmt.Errorf("%w", err)
+ }
+ }
+
+ di := DescriptorInput{
+ dt: t,
+ r: r,
+ opts: dopts,
+ }
+
+ return di, nil
+}
+
+// fillDescriptor fills d according to di. If di does not explicitly specify a time value, use t.
+func (di DescriptorInput) fillDescriptor(t time.Time, d *rawDescriptor) error {
+ d.DataType = di.dt
+ d.GroupID = di.opts.groupID | descrGroupMask
+ d.LinkedID = di.opts.linkID
+
+ if !di.opts.t.IsZero() {
+ t = di.opts.t
+ }
+ d.CreatedAt = t.Unix()
+ d.ModifiedAt = t.Unix()
+
+ d.UID = 0
+ d.GID = 0
+
+ if err := d.setName(di.opts.name); err != nil {
+ return err
+ }
+
+ return d.setExtra(di.opts.extra)
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/load.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/load.go
new file mode 100644
index 000000000..75266e194
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/load.go
@@ -0,0 +1,174 @@
+// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved.
+// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+// Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+)
+
+var (
+ errInvalidMagic = errors.New("invalid SIF magic")
+ errIncompatibleVersion = errors.New("incompatible SIF version")
+)
+
+// isValidSif looks at key fields from the global header to assess SIF validity.
+func isValidSif(f *FileImage) error {
+ if f.h.Magic != hdrMagic {
+ return errInvalidMagic
+ }
+
+ if f.h.Version != CurrentVersion.bytes() {
+ return errIncompatibleVersion
+ }
+
+ return nil
+}
+
+// populateMinIDs populates the minIDs field of f.
+func (f *FileImage) populateMinIDs() {
+ f.minIDs = make(map[uint32]uint32)
+ f.WithDescriptors(func(d Descriptor) bool {
+ if minID, ok := f.minIDs[d.raw.GroupID]; !ok || d.ID() < minID {
+ f.minIDs[d.raw.GroupID] = d.ID()
+ }
+ return false
+ })
+}
+
+// loadContainer loads a SIF image from rw.
+func loadContainer(rw ReadWriter) (*FileImage, error) {
+ f := FileImage{rw: rw}
+
+ // Read global header.
+ err := binary.Read(
+ io.NewSectionReader(rw, 0, int64(binary.Size(f.h))),
+ binary.LittleEndian,
+ &f.h,
+ )
+ if err != nil {
+ return nil, fmt.Errorf("reading global header: %w", err)
+ }
+
+ if err := isValidSif(&f); err != nil {
+ return nil, err
+ }
+
+ // Read descriptors.
+ f.rds = make([]rawDescriptor, f.h.DescriptorsTotal)
+ err = binary.Read(
+ io.NewSectionReader(rw, f.h.DescriptorsOffset, f.h.DescriptorsSize),
+ binary.LittleEndian,
+ &f.rds,
+ )
+ if err != nil {
+ return nil, fmt.Errorf("reading descriptors: %w", err)
+ }
+
+ f.populateMinIDs()
+
+ return &f, nil
+}
+
+// loadOpts accumulates container loading options.
+type loadOpts struct {
+ flag int
+ closeOnUnload bool
+}
+
+// LoadOpt are used to specify container loading options.
+type LoadOpt func(*loadOpts) error
+
+// OptLoadWithFlag specifies flag (os.O_RDONLY etc.) to be used when opening the container file.
+func OptLoadWithFlag(flag int) LoadOpt {
+ return func(lo *loadOpts) error {
+ lo.flag = flag
+ return nil
+ }
+}
+
+// OptLoadWithCloseOnUnload specifies whether the ReadWriter should be closed by UnloadContainer.
+// By default, the ReadWriter will be closed if it implements the io.Closer interface.
+func OptLoadWithCloseOnUnload(b bool) LoadOpt {
+ return func(lo *loadOpts) error {
+ lo.closeOnUnload = b
+ return nil
+ }
+}
+
+// LoadContainerFromPath loads a new SIF container from path, according to opts.
+//
+// On success, a FileImage is returned. The caller must call UnloadContainer to ensure resources
+// are released.
+//
+// By default, the file is opened for read and write access. To change this behavior, consider
+// using OptLoadWithFlag.
+func LoadContainerFromPath(path string, opts ...LoadOpt) (*FileImage, error) {
+ lo := loadOpts{
+ flag: os.O_RDWR,
+ }
+
+ for _, opt := range opts {
+ if err := opt(&lo); err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+ }
+
+ fp, err := os.OpenFile(path, lo.flag, 0)
+ if err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ f, err := loadContainer(fp)
+ if err != nil {
+ fp.Close()
+
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ f.closeOnUnload = true
+ return f, nil
+}
+
+// LoadContainer loads a new SIF container from rw, according to opts.
+//
+// On success, a FileImage is returned. The caller must call UnloadContainer to ensure resources
+// are released. By default, UnloadContainer will close rw if it implements the io.Closer
+// interface. To change this behavior, consider using OptLoadWithCloseOnUnload.
+func LoadContainer(rw ReadWriter, opts ...LoadOpt) (*FileImage, error) {
+ lo := loadOpts{
+ closeOnUnload: true,
+ }
+
+ for _, opt := range opts {
+ if err := opt(&lo); err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+ }
+
+ f, err := loadContainer(rw)
+ if err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ f.closeOnUnload = lo.closeOnUnload
+ return f, nil
+}
+
+// UnloadContainer unloads f, releasing associated resources.
+func (f *FileImage) UnloadContainer() error {
+ if c, ok := f.rw.(io.Closer); ok && f.closeOnUnload {
+ if err := c.Close(); err != nil {
+ return fmt.Errorf("%w", err)
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/select.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/select.go
new file mode 100644
index 000000000..635d6e89c
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/select.go
@@ -0,0 +1,210 @@
+// Copyright (c) 2021, Sylabs Inc. All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+package sif
+
+import (
+ "errors"
+ "fmt"
+)
+
+// ErrNoObjects is the error returned when an image contains no data objects.
+var ErrNoObjects = errors.New("no objects in image")
+
+// ErrObjectNotFound is the error returned when a data object is not found.
+var ErrObjectNotFound = errors.New("object not found")
+
+// ErrMultipleObjectsFound is the error returned when multiple data objects are found.
+var ErrMultipleObjectsFound = errors.New("multiple objects found")
+
+// ErrInvalidObjectID is the error returned when an invalid object ID is supplied.
+var ErrInvalidObjectID = errors.New("invalid object ID")
+
+// ErrInvalidGroupID is the error returned when an invalid group ID is supplied.
+var ErrInvalidGroupID = errors.New("invalid group ID")
+
+// DescriptorSelectorFunc returns true if d matches, and false otherwise.
+type DescriptorSelectorFunc func(d Descriptor) (bool, error)
+
+// WithDataType selects descriptors that have data type dt.
+func WithDataType(dt DataType) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ return d.DataType() == dt, nil
+ }
+}
+
+// WithID selects descriptors with a matching ID.
+func WithID(id uint32) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ if id == 0 {
+ return false, ErrInvalidObjectID
+ }
+ return d.ID() == id, nil
+ }
+}
+
+// WithNoGroup selects descriptors that are not contained within an object group.
+func WithNoGroup() DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ return d.GroupID() == 0, nil
+ }
+}
+
+// WithGroupID returns a selector func that selects descriptors with a matching groupID.
+func WithGroupID(groupID uint32) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ if groupID == 0 {
+ return false, ErrInvalidGroupID
+ }
+ return d.GroupID() == groupID, nil
+ }
+}
+
+// WithLinkedID selects descriptors that are linked to the data object with specified ID.
+func WithLinkedID(id uint32) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ if id == 0 {
+ return false, ErrInvalidObjectID
+ }
+ linkedID, isGroup := d.LinkedID()
+ return !isGroup && linkedID == id, nil
+ }
+}
+
+// WithLinkedGroupID selects descriptors that are linked to the data object group with specified
+// ID.
+func WithLinkedGroupID(groupID uint32) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ if groupID == 0 {
+ return false, ErrInvalidGroupID
+ }
+ linkedID, isGroup := d.LinkedID()
+ return isGroup && linkedID == groupID, nil
+ }
+}
+
+// WithPartitionType selects descriptors containing a partition of type pt.
+func WithPartitionType(pt PartType) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ return d.raw.isPartitionOfType(pt), nil
+ }
+}
+
+// descriptorFromRaw populates a Descriptor from rd.
+func (f *FileImage) descriptorFromRaw(rd *rawDescriptor) Descriptor {
+ return Descriptor{
+ raw: *rd,
+ r: f.rw,
+ relativeID: rd.ID - f.minIDs[rd.GroupID],
+ }
+}
+
+// GetDescriptors returns a slice of in-use descriptors for which all selector funcs return true.
+// If the image contains no data objects, an error wrapping ErrNoObjects is returned.
+func (f *FileImage) GetDescriptors(fns ...DescriptorSelectorFunc) ([]Descriptor, error) {
+ if f.DescriptorsFree() == f.DescriptorsTotal() {
+ return nil, fmt.Errorf("%w", ErrNoObjects)
+ }
+
+ var ds []Descriptor
+
+ err := f.withDescriptors(multiSelectorFunc(fns...), func(d *rawDescriptor) error {
+ ds = append(ds, f.descriptorFromRaw(d))
+ return nil
+ })
+ if err != nil {
+ return nil, fmt.Errorf("%w", err)
+ }
+
+ return ds, nil
+}
+
+// getDescriptor returns a pointer to the in-use descriptor selected by fns. If no descriptor is
+// selected by fns, ErrObjectNotFound is returned. If multiple descriptors are selected by fns,
+// ErrMultipleObjectsFound is returned.
+func (f *FileImage) getDescriptor(fns ...DescriptorSelectorFunc) (*rawDescriptor, error) {
+ var d *rawDescriptor
+
+ err := f.withDescriptors(multiSelectorFunc(fns...), func(found *rawDescriptor) error {
+ if d != nil {
+ return ErrMultipleObjectsFound
+ }
+ d = found
+ return nil
+ })
+
+ if err == nil && d == nil {
+ err = ErrObjectNotFound
+ }
+
+ return d, err
+}
+
+// GetDescriptor returns the in-use descriptor selected by fns. If the image contains no data
+// objects, an error wrapping ErrNoObjects is returned. If no descriptor is selected by fns, an
+// error wrapping ErrObjectNotFound is returned. If multiple descriptors are selected by fns, an
+// error wrapping ErrMultipleObjectsFound is returned.
+func (f *FileImage) GetDescriptor(fns ...DescriptorSelectorFunc) (Descriptor, error) {
+ if f.DescriptorsFree() == f.DescriptorsTotal() {
+ return Descriptor{}, fmt.Errorf("%w", ErrNoObjects)
+ }
+
+ d, err := f.getDescriptor(fns...)
+ if err != nil {
+ return Descriptor{}, fmt.Errorf("%w", err)
+ }
+
+ return f.descriptorFromRaw(d), nil
+}
+
+// multiSelectorFunc returns a DescriptorSelectorFunc that selects a descriptor iff all of fns
+// select the descriptor.
+func multiSelectorFunc(fns ...DescriptorSelectorFunc) DescriptorSelectorFunc {
+ return func(d Descriptor) (bool, error) {
+ for _, fn := range fns {
+ if ok, err := fn(d); !ok || err != nil {
+ return ok, err
+ }
+ }
+ return true, nil
+ }
+}
+
+// withDescriptors calls onMatchFn with each in-use descriptor in f for which selectFn returns
+// true. If selectFn or onMatchFn return a non-nil error, the iteration halts, and the error is
+// returned to the caller.
+func (f *FileImage) withDescriptors(selectFn DescriptorSelectorFunc, onMatchFn func(*rawDescriptor) error) error {
+ for i, d := range f.rds {
+ if !d.Used {
+ continue
+ }
+
+ if ok, err := selectFn(f.descriptorFromRaw(&f.rds[i])); err != nil {
+ return err
+ } else if !ok {
+ continue
+ }
+
+ if err := onMatchFn(&f.rds[i]); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+var errAbort = errors.New("abort")
+
+// abortOnMatch is a semantic convenience function that always returns a non-nil error, which can
+// be used as a no-op matchFn.
+func abortOnMatch(*rawDescriptor) error { return errAbort }
+
+// WithDescriptors calls fn with each in-use descriptor in f, until fn returns true.
+func (f *FileImage) WithDescriptors(fn func(d Descriptor) bool) {
+ selectFn := func(d Descriptor) (bool, error) {
+ return fn(d), nil
+ }
+ _ = f.withDescriptors(selectFn, abortOnMatch)
+}
diff --git a/vendor/github.com/sylabs/sif/v2/pkg/sif/sif.go b/vendor/github.com/sylabs/sif/v2/pkg/sif/sif.go
new file mode 100644
index 000000000..704acee4a
--- /dev/null
+++ b/vendor/github.com/sylabs/sif/v2/pkg/sif/sif.go
@@ -0,0 +1,364 @@
+// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved.
+// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
+// Copyright (c) 2017, Yannick Cote <yhcote@gmail.com> All rights reserved.
+// This software is licensed under a 3-clause BSD license. Please consult the
+// LICENSE file distributed with the sources of this project regarding your
+// rights to use or distribute this software.
+
+// Package sif implements data structures and routines to create
+// and access SIF files.
+//
+// Layout of a SIF file (example):
+//
+// .================================================.
+// | GLOBAL HEADER: Sifheader |
+// | - launch: "#!/usr/bin/env..." |
+// | - magic: "SIF_MAGIC" |
+// | - version: "1" |
+// | - arch: "4" |
+// | - uuid: b2659d4e-bd50-4ea5-bd17-eec5e54f918e |
+// | - ctime: 1504657553 |
+// | - mtime: 1504657653 |
+// | - ndescr: 3 |
+// | - descroff: 120 | --.
+// | - descrlen: 432 | |
+// | - dataoff: 4096 | |
+// | - datalen: 619362 | |
+// |------------------------------------------------| <-'
+// | DESCR[0]: Sifdeffile |
+// | - Sifcommon |
+// | - datatype: DATA_DEFFILE |
+// | - id: 1 |
+// | - groupid: 1 |
+// | - link: NONE |
+// | - fileoff: 4096 | --.
+// | - filelen: 222 | |
+// |------------------------------------------------| <-----.
+// | DESCR[1]: Sifpartition | | |
+// | - Sifcommon | | |
+// | - datatype: DATA_PARTITION | | |
+// | - id: 2 | | |
+// | - groupid: 1 | | |
+// | - link: NONE | | |
+// | - fileoff: 4318 | ----. |
+// | - filelen: 618496 | | | |
+// | - fstype: Squashfs | | | |
+// | - parttype: System | | | |
+// | - content: Linux | | | |
+// |------------------------------------------------| | | |
+// | DESCR[2]: Sifsignature | | | |
+// | - Sifcommon | | | |
+// | - datatype: DATA_SIGNATURE | | | |
+// | - id: 3 | | | |
+// | - groupid: NONE | | | |
+// | - link: 2 | ------'
+// | - fileoff: 622814 | ------.
+// | - filelen: 644 | | | |
+// | - hashtype: SHA384 | | | |
+// | - entity: @ | | | |
+// |------------------------------------------------| <-' | |
+// | Definition file data | | |
+// | . | | |
+// | . | | |
+// | . | | |
+// |------------------------------------------------| <---' |
+// | File system partition image | |
+// | . | |
+// | . | |
+// | . | |
+// |------------------------------------------------| <-----'
+// | Signed verification data |
+// | . |
+// | . |
+// | . |
+// `================================================'
+//
+package sif
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "time"
+
+ "github.com/google/uuid"
+)
+
+// SIF header constants and quantities.
+const (
+ hdrLaunchLen = 32 // len("#!/usr/bin/env... ")
+ hdrMagicLen = 10 // len("SIF_MAGIC")
+ hdrVersionLen = 3 // len("99")
+)
+
+var hdrMagic = [...]byte{'S', 'I', 'F', '_', 'M', 'A', 'G', 'I', 'C', '\x00'}
+
+// SpecVersion specifies a SIF specification version.
+type SpecVersion uint8
+
+func (v SpecVersion) String() string { return fmt.Sprintf("%02d", v) }
+
+// bytes returns the value of b, formatted for direct inclusion in a SIF header.
+func (v SpecVersion) bytes() [hdrVersionLen]byte {
+ var b [3]byte
+ copy(b[:], fmt.Sprintf("%02d", v))
+ return b
+}
+
+// SIF specification versions.
+const (
+ version01 SpecVersion = iota + 1
+)
+
+// CurrentVersion specifies the current SIF specification version.
+const CurrentVersion = version01
+
+const (
+ descrGroupMask = 0xf0000000 // groups start at that offset
+ descrEntityLen = 256 // len("Joe Bloe <jbloe@gmail.com>...")
+ descrNameLen = 128 // descriptor name (string identifier)
+ descrMaxPrivLen = 384 // size reserved for descriptor specific data
+)
+
+// DataType represents the different SIF data object types stored in the image.
+type DataType int32
+
+// List of supported SIF data types.
+const (
+ DataDeffile DataType = iota + 0x4001 // definition file data object
+ DataEnvVar // environment variables data object
+ DataLabels // JSON labels data object
+ DataPartition // file system data object
+ DataSignature // signing/verification data object
+ DataGenericJSON // generic JSON meta-data
+ DataGeneric // generic / raw data
+ DataCryptoMessage // cryptographic message data object
+)
+
+// String returns a human-readable representation of t.
+func (t DataType) String() string {
+ switch t {
+ case DataDeffile:
+ return "Def.FILE"
+ case DataEnvVar:
+ return "Env.Vars"
+ case DataLabels:
+ return "JSON.Labels"
+ case DataPartition:
+ return "FS"
+ case DataSignature:
+ return "Signature"
+ case DataGenericJSON:
+ return "JSON.Generic"
+ case DataGeneric:
+ return "Generic/Raw"
+ case DataCryptoMessage:
+ return "Cryptographic Message"
+ }
+ return "Unknown"
+}
+
+// FSType represents the different SIF file system types found in partition data objects.
+type FSType int32
+
+// List of supported file systems.
+const (
+ FsSquash FSType = iota + 1 // Squashfs file system, RDONLY
+ FsExt3 // EXT3 file system, RDWR (deprecated)
+ FsImmuObj // immutable data object archive
+ FsRaw // raw data
+ FsEncryptedSquashfs // Encrypted Squashfs file system, RDONLY
+)
+
+// String returns a human-readable representation of t.
+func (t FSType) String() string {
+ switch t {
+ case FsSquash:
+ return "Squashfs"
+ case FsExt3:
+ return "Ext3"
+ case FsImmuObj:
+ return "Archive"
+ case FsRaw:
+ return "Raw"
+ case FsEncryptedSquashfs:
+ return "Encrypted squashfs"
+ }
+ return "Unknown"
+}
+
+// PartType represents the different SIF container partition types (system and data).
+type PartType int32
+
+// List of supported partition types.
+const (
+ PartSystem PartType = iota + 1 // partition hosts an operating system
+ PartPrimSys // partition hosts the primary operating system
+ PartData // partition hosts data only
+ PartOverlay // partition hosts an overlay
+)
+
+// String returns a human-readable representation of t.
+func (t PartType) String() string {
+ switch t {
+ case PartSystem:
+ return "System"
+ case PartPrimSys:
+ return "*System"
+ case PartData:
+ return "Data"
+ case PartOverlay:
+ return "Overlay"
+ }
+ return "Unknown"
+}
+
+// hashType represents the different SIF hashing function types used to fingerprint data objects.
+type hashType int32
+
+// List of supported hash functions.
+const (
+ hashSHA256 hashType = iota + 1
+ hashSHA384
+ hashSHA512
+ hashBLAKE2S
+ hashBLAKE2B
+)
+
+// FormatType represents the different formats used to store cryptographic message objects.
+type FormatType int32
+
+// List of supported cryptographic message formats.
+const (
+ FormatOpenPGP FormatType = iota + 1
+ FormatPEM
+)
+
+// String returns a human-readable representation of t.
+func (t FormatType) String() string {
+ switch t {
+ case FormatOpenPGP:
+ return "OpenPGP"
+ case FormatPEM:
+ return "PEM"
+ }
+ return "Unknown"
+}
+
+// MessageType represents the different messages stored within cryptographic message objects.
+type MessageType int32
+
+// List of supported cryptographic message formats.
+const (
+ // openPGP formatted messages.
+ MessageClearSignature MessageType = 0x100
+
+ // PEM formatted messages.
+ MessageRSAOAEP MessageType = 0x200
+)
+
+// String returns a human-readable representation of t.
+func (t MessageType) String() string {
+ switch t {
+ case MessageClearSignature:
+ return "Clear Signature"
+ case MessageRSAOAEP:
+ return "RSA-OAEP"
+ }
+ return "Unknown"
+}
+
+// header describes a loaded SIF file.
+type header struct {
+ LaunchScript [hdrLaunchLen]byte
+
+ Magic [hdrMagicLen]byte
+ Version [hdrVersionLen]byte
+ Arch archType
+ ID uuid.UUID
+
+ CreatedAt int64
+ ModifiedAt int64
+
+ DescriptorsFree int64
+ DescriptorsTotal int64
+ DescriptorsOffset int64
+ DescriptorsSize int64
+ DataOffset int64
+ DataSize int64
+}
+
+// GetIntegrityReader returns an io.Reader that reads the integrity-protected fields from h.
+func (h header) GetIntegrityReader() io.Reader {
+ return io.MultiReader(
+ bytes.NewReader(h.LaunchScript[:]),
+ bytes.NewReader(h.Magic[:]),
+ bytes.NewReader(h.Version[:]),
+ bytes.NewReader(h.ID[:]),
+ )
+}
+
+// ReadWriter describes the interface required to read and write SIF images.
+type ReadWriter interface {
+ io.ReaderAt
+ io.WriteSeeker
+ Truncate(int64) error
+}
+
+// FileImage describes the representation of a SIF file in memory.
+type FileImage struct {
+ rw ReadWriter // Backing storage for image.
+
+ h header // Raw global header from image.
+ rds []rawDescriptor // Raw descriptors from image.
+
+ closeOnUnload bool // Close rw on Unload.
+ minIDs map[uint32]uint32 // Minimum object IDs for each group ID.
+}
+
+// LaunchScript returns the image launch script.
+func (f *FileImage) LaunchScript() string {
+ return string(bytes.TrimRight(f.h.LaunchScript[:], "\x00"))
+}
+
+// Version returns the SIF specification version of the image.
+func (f *FileImage) Version() string {
+ return string(bytes.TrimRight(f.h.Version[:], "\x00"))
+}
+
+// PrimaryArch returns the primary CPU architecture of the image, or "unknown" if the primary CPU
+// architecture cannot be determined.
+func (f *FileImage) PrimaryArch() string { return f.h.Arch.GoArch() }
+
+// ID returns the ID of the image.
+func (f *FileImage) ID() string { return f.h.ID.String() }
+
+// CreatedAt returns the creation time of the image.
+func (f *FileImage) CreatedAt() time.Time { return time.Unix(f.h.CreatedAt, 0) }
+
+// ModifiedAt returns the last modification time of the image.
+func (f *FileImage) ModifiedAt() time.Time { return time.Unix(f.h.ModifiedAt, 0) }
+
+// DescriptorsFree returns the number of free descriptors in the image.
+func (f *FileImage) DescriptorsFree() int64 { return f.h.DescriptorsFree }
+
+// DescriptorsTotal returns the total number of descriptors in the image.
+func (f *FileImage) DescriptorsTotal() int64 { return f.h.DescriptorsTotal }
+
+// DescriptorsOffset returns the offset (in bytes) of the descriptors section in the image.
+func (f *FileImage) DescriptorsOffset() int64 { return f.h.DescriptorsOffset }
+
+// DescriptorsSize returns the size (in bytes) of the descriptors section in the image.
+func (f *FileImage) DescriptorsSize() int64 { return f.h.DescriptorsSize }
+
+// DataOffset returns the offset (in bytes) of the data section in the image.
+func (f *FileImage) DataOffset() int64 { return f.h.DataOffset }
+
+// DataSize returns the size (in bytes) of the data section in the image.
+func (f *FileImage) DataSize() int64 { return f.h.DataSize }
+
+// GetHeaderIntegrityReader returns an io.Reader that reads the integrity-protected fields from the
+// header of the image.
+func (f *FileImage) GetHeaderIntegrityReader() io.Reader {
+ return f.h.GetIntegrityReader()
+}
diff --git a/vendor/github.com/vbauerster/mpb/v7/bar.go b/vendor/github.com/vbauerster/mpb/v7/bar.go
index 35644a411..646cb471a 100644
--- a/vendor/github.com/vbauerster/mpb/v7/bar.go
+++ b/vendor/github.com/vbauerster/mpb/v7/bar.go
@@ -5,7 +5,6 @@ import (
"context"
"fmt"
"io"
- "log"
"runtime/debug"
"strings"
"sync"
@@ -36,7 +35,6 @@ type Bar struct {
cacheState *bState
container *Progress
- dlogger *log.Logger
recoveredPanic interface{}
}
@@ -64,7 +62,7 @@ type bState struct {
averageDecorators []decor.AverageDecorator
ewmaDecorators []decor.EwmaDecorator
shutdownListeners []decor.ShutdownListener
- bufP, bufB, bufA *bytes.Buffer
+ buffers [3]*bytes.Buffer
filler BarFiller
middleware func(BarFiller) BarFiller
extender extenderFunc
@@ -81,7 +79,6 @@ type frame struct {
}
func newBar(container *Progress, bs *bState) *Bar {
- logPrefix := fmt.Sprintf("%sbar#%02d ", container.dlogger.Prefix(), bs.id)
ctx, cancel := context.WithCancel(container.ctx)
bar := &Bar{
@@ -93,7 +90,6 @@ func newBar(container *Progress, bs *bState) *Bar {
frameCh: make(chan *frame, 1),
done: make(chan struct{}),
cancel: cancel,
- dlogger: log.New(bs.debugOut, logPrefix, log.Lshortfile),
}
go bar.serve(ctx, bs)
@@ -106,7 +102,7 @@ func (b *Bar) ProxyReader(r io.Reader) io.ReadCloser {
if r == nil {
panic("expected non nil io.Reader")
}
- return newProxyReader(r, b)
+ return b.newProxyReader(r)
}
// ID returs id of the bar.
@@ -279,7 +275,7 @@ func (b *Bar) Abort(drop bool) {
done := make(chan struct{})
select {
case b.operateState <- func(s *bState) {
- if s.completed == true {
+ if s.completed {
close(done)
return
}
@@ -346,13 +342,16 @@ func (b *Bar) render(tw int) {
// recovering if user defined decorator panics for example
if p := recover(); p != nil {
if b.recoveredPanic == nil {
+ if s.debugOut != nil {
+ fmt.Fprintln(s.debugOut, p)
+ _, _ = s.debugOut.Write(debug.Stack())
+ }
s.extender = makePanicExtender(p)
b.toShutdown = !b.toShutdown
b.recoveredPanic = p
}
reader, lines := s.extender(nil, s.reqWidth, stat)
b.frameCh <- &frame{reader, lines + 1}
- b.dlogger.Println(p)
}
s.completeFlushed = s.completed
}()
@@ -429,40 +428,41 @@ func (b *Bar) wSyncTable() [][]chan int {
}
func (s *bState) draw(stat decor.Statistics) io.Reader {
+ bufP, bufB, bufA := s.buffers[0], s.buffers[1], s.buffers[2]
nlr := strings.NewReader("\n")
tw := stat.AvailableWidth
for _, d := range s.pDecorators {
str := d.Decor(stat)
stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str))
- s.bufP.WriteString(str)
+ bufP.WriteString(str)
}
if stat.AvailableWidth < 1 {
- trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufP.String()), tw, "…"))
- s.bufP.Reset()
+ trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(bufP.String()), tw, "…"))
+ bufP.Reset()
return io.MultiReader(trunc, nlr)
}
if !s.trimSpace && stat.AvailableWidth > 1 {
stat.AvailableWidth -= 2
- s.bufB.WriteByte(' ')
- defer s.bufB.WriteByte(' ')
+ bufB.WriteByte(' ')
+ defer bufB.WriteByte(' ')
}
tw = stat.AvailableWidth
for _, d := range s.aDecorators {
str := d.Decor(stat)
stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str))
- s.bufA.WriteString(str)
+ bufA.WriteString(str)
}
if stat.AvailableWidth < 1 {
- trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufA.String()), tw, "…"))
- s.bufA.Reset()
- return io.MultiReader(s.bufP, s.bufB, trunc, nlr)
+ trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(bufA.String()), tw, "…"))
+ bufA.Reset()
+ return io.MultiReader(bufP, bufB, trunc, nlr)
}
- s.filler.Fill(s.bufB, s.reqWidth, stat)
+ s.filler.Fill(bufB, s.reqWidth, stat)
- return io.MultiReader(s.bufP, s.bufB, s.bufA, nlr)
+ return io.MultiReader(bufP, bufB, bufA, nlr)
}
func (s *bState) wSyncTable() [][]chan int {
@@ -489,39 +489,51 @@ func (s *bState) wSyncTable() [][]chan int {
func (s bState) decoratorEwmaUpdate(dur time.Duration) {
wg := new(sync.WaitGroup)
- wg.Add(len(s.ewmaDecorators))
- for _, d := range s.ewmaDecorators {
- d := d
- go func() {
+ for i := 0; i < len(s.ewmaDecorators); i++ {
+ switch d := s.ewmaDecorators[i]; i {
+ case len(s.ewmaDecorators) - 1:
d.EwmaUpdate(s.lastIncrement, dur)
- wg.Done()
- }()
+ default:
+ wg.Add(1)
+ go func() {
+ d.EwmaUpdate(s.lastIncrement, dur)
+ wg.Done()
+ }()
+ }
}
wg.Wait()
}
func (s bState) decoratorAverageAdjust(start time.Time) {
wg := new(sync.WaitGroup)
- wg.Add(len(s.averageDecorators))
- for _, d := range s.averageDecorators {
- d := d
- go func() {
+ for i := 0; i < len(s.averageDecorators); i++ {
+ switch d := s.averageDecorators[i]; i {
+ case len(s.averageDecorators) - 1:
d.AverageAdjust(start)
- wg.Done()
- }()
+ default:
+ wg.Add(1)
+ go func() {
+ d.AverageAdjust(start)
+ wg.Done()
+ }()
+ }
}
wg.Wait()
}
func (s bState) decoratorShutdownNotify() {
wg := new(sync.WaitGroup)
- wg.Add(len(s.shutdownListeners))
- for _, d := range s.shutdownListeners {
- d := d
- go func() {
+ for i := 0; i < len(s.shutdownListeners); i++ {
+ switch d := s.shutdownListeners[i]; i {
+ case len(s.shutdownListeners) - 1:
d.Shutdown()
- wg.Done()
- }()
+ default:
+ wg.Add(1)
+ go func() {
+ d.Shutdown()
+ wg.Done()
+ }()
+ }
}
wg.Wait()
}
@@ -547,14 +559,11 @@ func extractBaseDecorator(d decor.Decorator) decor.Decorator {
func makePanicExtender(p interface{}) extenderFunc {
pstr := fmt.Sprint(p)
- stack := debug.Stack()
- stackLines := bytes.Count(stack, []byte("\n"))
return func(_ io.Reader, _ int, st decor.Statistics) (io.Reader, int) {
mr := io.MultiReader(
strings.NewReader(runewidth.Truncate(pstr, st.AvailableWidth, "…")),
- strings.NewReader(fmt.Sprintf("\n%#v\n", st)),
- bytes.NewReader(stack),
+ strings.NewReader("\n"),
)
- return mr, stackLines + 1
+ return mr, 0
}
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go b/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go
index 80b210455..54b7bfd6f 100644
--- a/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go
+++ b/vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go
@@ -32,13 +32,13 @@ type BarStyleComposer interface {
}
type bFiller struct {
+ rev bool
components [components]*component
tip struct {
count uint
onComplete *component
frames []*component
}
- flush func(dst io.Writer, filling, padding [][]byte)
}
type component struct {
@@ -113,14 +113,7 @@ func (s *barStyle) Reverse() BarStyleComposer {
}
func (s *barStyle) Build() BarFiller {
- bf := new(bFiller)
- if s.rev {
- bf.flush = func(dst io.Writer, filling, padding [][]byte) {
- flush(dst, padding, filling)
- }
- } else {
- bf.flush = flush
- }
+ bf := &bFiller{rev: s.rev}
bf.components[iLbound] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.lbound)),
bytes: []byte(s.lbound),
@@ -164,8 +157,9 @@ func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
return
}
- w.Write(s.components[iLbound].bytes)
- defer w.Write(s.components[iRbound].bytes)
+ ow := optimisticWriter(w)
+ ow(s.components[iLbound].bytes)
+ defer ow(s.components[iRbound].bytes)
if width == 0 {
return
@@ -236,14 +230,27 @@ func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
}
}
- s.flush(w, filling, padding)
+ if s.rev {
+ flush(ow, padding, filling)
+ } else {
+ flush(ow, filling, padding)
+ }
}
-func flush(dst io.Writer, filling, padding [][]byte) {
+func flush(ow func([]byte), filling, padding [][]byte) {
for i := len(filling) - 1; i >= 0; i-- {
- dst.Write(filling[i])
+ ow(filling[i])
}
for i := 0; i < len(padding); i++ {
- dst.Write(padding[i])
+ ow(padding[i])
+ }
+}
+
+func optimisticWriter(w io.Writer) func([]byte) {
+ return func(p []byte) {
+ _, err := w.Write(p)
+ if err != nil {
+ panic(err)
+ }
}
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go b/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go
index 58ae1c532..d38525efc 100644
--- a/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go
+++ b/vendor/github.com/vbauerster/mpb/v7/bar_filler_spinner.go
@@ -73,15 +73,19 @@ func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
return
}
+ var err error
rest := width - frameWidth
switch s.position {
case positionLeft:
- io.WriteString(w, frame+strings.Repeat(" ", rest))
+ _, err = io.WriteString(w, frame+strings.Repeat(" ", rest))
case positionRight:
- io.WriteString(w, strings.Repeat(" ", rest)+frame)
+ _, err = io.WriteString(w, strings.Repeat(" ", rest)+frame)
default:
str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2)
- io.WriteString(w, str)
+ _, err = io.WriteString(w, str)
+ }
+ if err != nil {
+ panic(err)
}
s.count++
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/bar_option.go b/vendor/github.com/vbauerster/mpb/v7/bar_option.go
index 660e7c487..4ba490505 100644
--- a/vendor/github.com/vbauerster/mpb/v7/bar_option.go
+++ b/vendor/github.com/vbauerster/mpb/v7/bar_option.go
@@ -89,7 +89,10 @@ func BarFillerOnComplete(message string) BarOption {
return BarFillerMiddleware(func(base BarFiller) BarFiller {
return BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
if st.Completed {
- io.WriteString(w, message)
+ _, err := io.WriteString(w, message)
+ if err != nil {
+ panic(err)
+ }
} else {
base.Fill(w, reqWidth, st)
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go
index 925c8b1dc..eaf541cb7 100644
--- a/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go
+++ b/vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go
@@ -76,9 +76,9 @@ func (w *Writer) GetWidth() (int, error) {
return tw, err
}
-func (w *Writer) ansiCuuAndEd() (err error) {
+func (w *Writer) ansiCuuAndEd() error {
buf := make([]byte, 8)
buf = strconv.AppendInt(buf[:copy(buf, escOpen)], int64(w.lines), 10)
- _, err = w.out.Write(append(buf, cuuAndEd...))
- return
+ _, err := w.out.Write(append(buf, cuuAndEd...))
+ return err
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/optimistic_string_writer.go b/vendor/github.com/vbauerster/mpb/v7/decor/optimistic_string_writer.go
new file mode 100644
index 000000000..ea9fda79d
--- /dev/null
+++ b/vendor/github.com/vbauerster/mpb/v7/decor/optimistic_string_writer.go
@@ -0,0 +1,12 @@
+package decor
+
+import "io"
+
+func optimisticStringWriter(w io.Writer) func(string) {
+ return func(s string) {
+ _, err := io.WriteString(w, s)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go b/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go
index 2b0a7a956..6e7f5c6ed 100644
--- a/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go
+++ b/vendor/github.com/vbauerster/mpb/v7/decor/percentage.go
@@ -2,7 +2,6 @@ package decor
import (
"fmt"
- "io"
"strconv"
"github.com/vbauerster/mpb/v7/internal"
@@ -24,12 +23,12 @@ func (s percentageType) Format(st fmt.State, verb rune) {
}
}
- io.WriteString(st, strconv.FormatFloat(float64(s), 'f', prec, 64))
-
+ osw := optimisticStringWriter(st)
+ osw(strconv.FormatFloat(float64(s), 'f', prec, 64))
if st.Flag(' ') {
- io.WriteString(st, " ")
+ osw(" ")
}
- io.WriteString(st, "%")
+ osw("%")
}
// Percentage returns percentage decorator. It's a wrapper of NewPercentage.
diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go b/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go
index e4b974058..12879b8f1 100644
--- a/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go
+++ b/vendor/github.com/vbauerster/mpb/v7/decor/size_type.go
@@ -2,8 +2,6 @@ package decor
import (
"fmt"
- "io"
- "math"
"strconv"
)
@@ -47,16 +45,16 @@ func (self SizeB1024) Format(st fmt.State, verb rune) {
unit = _iMiB
case self < _iTiB:
unit = _iGiB
- case self <= math.MaxInt64:
+ default:
unit = _iTiB
}
- io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
-
+ osw := optimisticStringWriter(st)
+ osw(strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
if st.Flag(' ') {
- io.WriteString(st, " ")
+ osw(" ")
}
- io.WriteString(st, unit.String())
+ osw(unit.String())
}
const (
@@ -96,14 +94,14 @@ func (self SizeB1000) Format(st fmt.State, verb rune) {
unit = _MB
case self < _TB:
unit = _GB
- case self <= math.MaxInt64:
+ default:
unit = _TB
}
- io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
-
+ osw := optimisticStringWriter(st)
+ osw(strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
if st.Flag(' ') {
- io.WriteString(st, " ")
+ osw(" ")
}
- io.WriteString(st, unit.String())
+ osw(unit.String())
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/decor/speed.go b/vendor/github.com/vbauerster/mpb/v7/decor/speed.go
index 634edabfd..99cfde2bf 100644
--- a/vendor/github.com/vbauerster/mpb/v7/decor/speed.go
+++ b/vendor/github.com/vbauerster/mpb/v7/decor/speed.go
@@ -2,7 +2,6 @@ package decor
import (
"fmt"
- "io"
"math"
"time"
@@ -24,7 +23,7 @@ type speedFormatter struct {
func (self *speedFormatter) Format(st fmt.State, verb rune) {
self.Formatter.Format(st, verb)
- io.WriteString(st, "/s")
+ optimisticStringWriter(st)("/s")
}
// EwmaSpeed exponential-weighted-moving-average based speed decorator.
diff --git a/vendor/github.com/vbauerster/mpb/v7/go.mod b/vendor/github.com/vbauerster/mpb/v7/go.mod
index 19a6f8044..8fa790dc7 100644
--- a/vendor/github.com/vbauerster/mpb/v7/go.mod
+++ b/vendor/github.com/vbauerster/mpb/v7/go.mod
@@ -4,7 +4,7 @@ require (
github.com/VividCortex/ewma v1.2.0
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/mattn/go-runewidth v0.0.13
- golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
)
go 1.14
diff --git a/vendor/github.com/vbauerster/mpb/v7/go.sum b/vendor/github.com/vbauerster/mpb/v7/go.sum
index b4388d9ea..aebe4d9d2 100644
--- a/vendor/github.com/vbauerster/mpb/v7/go.sum
+++ b/vendor/github.com/vbauerster/mpb/v7/go.sum
@@ -6,5 +6,5 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d h1:1oIt9o40TWWI9FUaveVpUvBe13FNqBNVXy3ue2fcfkw=
-golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/vendor/github.com/vbauerster/mpb/v7/progress.go b/vendor/github.com/vbauerster/mpb/v7/progress.go
index 46485f719..123af17cf 100644
--- a/vendor/github.com/vbauerster/mpb/v7/progress.go
+++ b/vendor/github.com/vbauerster/mpb/v7/progress.go
@@ -6,8 +6,6 @@ import (
"context"
"fmt"
"io"
- "io/ioutil"
- "log"
"math"
"os"
"sync"
@@ -33,7 +31,6 @@ type Progress struct {
done chan struct{}
refreshCh chan time.Time
once sync.Once
- dlogger *log.Logger
}
// pState holds bars in its priorityQueue. It gets passed to
@@ -75,7 +72,6 @@ func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
rr: prr,
parkedBars: make(map[*Bar]*Bar),
output: os.Stdout,
- debugOut: ioutil.Discard,
}
for _, opt := range options {
@@ -91,7 +87,6 @@ func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
bwg: new(sync.WaitGroup),
operateState: make(chan func(*pState)),
done: make(chan struct{}),
- dlogger: log.New(s.debugOut, "[mpb] ", log.Lshortfile),
}
p.cwg.Add(1)
@@ -234,12 +229,26 @@ func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
op(s)
case <-p.refreshCh:
if err := s.render(cw); err != nil {
- p.dlogger.Println(err)
+ if s.debugOut != nil {
+ _, e := fmt.Fprintln(s.debugOut, err)
+ if e != nil {
+ panic(err)
+ }
+ } else {
+ panic(err)
+ }
}
case <-s.shutdownNotifier:
for s.heapUpdated {
if err := s.render(cw); err != nil {
- p.dlogger.Println(err)
+ if s.debugOut != nil {
+ _, e := fmt.Fprintln(s.debugOut, err)
+ if e != nil {
+ panic(err)
+ }
+ } else {
+ panic(err)
+ }
}
}
return
@@ -311,7 +320,10 @@ func (s *pState) flush(cw *cwriter.Writer) error {
for s.bHeap.Len() > 0 {
b := heap.Pop(&s.bHeap).(*Bar)
frame := <-b.frameCh
- cw.ReadFrom(frame.reader)
+ _, err := cw.ReadFrom(frame.reader)
+ if err != nil {
+ return err
+ }
if b.toShutdown {
if b.recoveredPanic != nil {
s.barShutdownQueue = append(s.barShutdownQueue, b)
@@ -402,9 +414,9 @@ func (s *pState) makeBarState(total int64, filler BarFiller, options ...BarOptio
bs.priority = -(math.MaxInt32 - s.idCount)
}
- bs.bufP = bytes.NewBuffer(make([]byte, 0, 128))
- bs.bufB = bytes.NewBuffer(make([]byte, 0, 256))
- bs.bufA = bytes.NewBuffer(make([]byte, 0, 128))
+ for i := 0; i < len(bs.buffers); i++ {
+ bs.buffers[i] = bytes.NewBuffer(make([]byte, 0, 512))
+ }
return bs
}
diff --git a/vendor/github.com/vbauerster/mpb/v7/proxyreader.go b/vendor/github.com/vbauerster/mpb/v7/proxyreader.go
index a16f5ec8a..25f195bb8 100644
--- a/vendor/github.com/vbauerster/mpb/v7/proxyreader.go
+++ b/vendor/github.com/vbauerster/mpb/v7/proxyreader.go
@@ -11,7 +11,7 @@ type proxyReader struct {
bar *Bar
}
-func (x *proxyReader) Read(p []byte) (int, error) {
+func (x proxyReader) Read(p []byte) (int, error) {
n, err := x.ReadCloser.Read(p)
x.bar.IncrBy(n)
if err == io.EOF {
@@ -21,12 +21,11 @@ func (x *proxyReader) Read(p []byte) (int, error) {
}
type proxyWriterTo struct {
- io.ReadCloser // *proxyReader
- wt io.WriterTo
- bar *Bar
+ proxyReader
+ wt io.WriterTo
}
-func (x *proxyWriterTo) WriteTo(w io.Writer) (int64, error) {
+func (x proxyWriterTo) WriteTo(w io.Writer) (int64, error) {
n, err := x.wt.WriteTo(w)
x.bar.IncrInt64(n)
if err == io.EOF {
@@ -36,13 +35,12 @@ func (x *proxyWriterTo) WriteTo(w io.Writer) (int64, error) {
}
type ewmaProxyReader struct {
- io.ReadCloser // *proxyReader
- bar *Bar
+ proxyReader
}
-func (x *ewmaProxyReader) Read(p []byte) (int, error) {
+func (x ewmaProxyReader) Read(p []byte) (int, error) {
start := time.Now()
- n, err := x.ReadCloser.Read(p)
+ n, err := x.proxyReader.Read(p)
if n > 0 {
x.bar.DecoratorEwmaUpdate(time.Since(start))
}
@@ -50,12 +48,11 @@ func (x *ewmaProxyReader) Read(p []byte) (int, error) {
}
type ewmaProxyWriterTo struct {
- io.ReadCloser // *ewmaProxyReader
- wt io.WriterTo // *proxyWriterTo
- bar *Bar
+ ewmaProxyReader
+ wt proxyWriterTo
}
-func (x *ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) {
+func (x ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) {
start := time.Now()
n, err := x.wt.WriteTo(w)
if n > 0 {
@@ -64,17 +61,19 @@ func (x *ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) {
return n, err
}
-func newProxyReader(r io.Reader, bar *Bar) io.ReadCloser {
- rc := toReadCloser(r)
- rc = &proxyReader{rc, bar}
-
- if wt, isWriterTo := r.(io.WriterTo); bar.hasEwmaDecorators {
- rc = &ewmaProxyReader{rc, bar}
- if isWriterTo {
- rc = &ewmaProxyWriterTo{rc, wt, bar}
+func (b *Bar) newProxyReader(r io.Reader) (rc io.ReadCloser) {
+ pr := proxyReader{toReadCloser(r), b}
+ if wt, ok := r.(io.WriterTo); ok {
+ pw := proxyWriterTo{pr, wt}
+ if b.hasEwmaDecorators {
+ rc = ewmaProxyWriterTo{ewmaProxyReader{pr}, pw}
+ } else {
+ rc = pw
}
- } else if isWriterTo {
- rc = &proxyWriterTo{rc, wt, bar}
+ } else if b.hasEwmaDecorators {
+ rc = ewmaProxyReader{pr}
+ } else {
+ rc = pr
}
return rc
}
diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml
deleted file mode 100644
index 80219c69d..000000000
--- a/vendor/github.com/vishvananda/netlink/.travis.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-language: go
-go:
- - "1.12.x"
- - "1.13.x"
- - "1.14.x"
-before_script:
- # make sure we keep path in tact when we sudo
- - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
- # modprobe ip_gre or else the first gre device can't be deleted
- - sudo modprobe ip_gre
- # modprobe nf_conntrack for the conntrack testing
- - sudo modprobe nf_conntrack
- - sudo modprobe nf_conntrack_netlink
- - sudo modprobe nf_conntrack_ipv4
- - sudo modprobe nf_conntrack_ipv6
- - sudo modprobe sch_hfsc
- - sudo modprobe sch_sfq
-install:
- - go get -v -t ./...
-go_import_path: github.com/vishvananda/netlink
diff --git a/vendor/github.com/vishvananda/netlink/README.md b/vendor/github.com/vishvananda/netlink/README.md
index a88e2f418..0128bc67d 100644
--- a/vendor/github.com/vishvananda/netlink/README.md
+++ b/vendor/github.com/vishvananda/netlink/README.md
@@ -1,6 +1,6 @@
# netlink - netlink library for go #
-[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink)
+![Build Status](https://github.com/vishvananda/netlink/actions/workflows/main.yml/badge.svg) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink)
The netlink package provides a simple netlink library for go. Netlink
is the interface a user-space program in linux uses to communicate with
diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go
index 71da251ca..e4a167dda 100644
--- a/vendor/github.com/vishvananda/netlink/addr_linux.go
+++ b/vendor/github.com/vishvananda/netlink/addr_linux.go
@@ -268,7 +268,7 @@ func parseAddr(m []byte) (addr Addr, family int, err error) {
// But obviously, as there are IPv6 PtP addresses, too,
// IFA_LOCAL should also be handled for IPv6.
if local != nil {
- if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
+ if family == FAMILY_V4 && dst != nil && local.IP.Equal(dst.IP) {
addr.IPNet = dst
} else {
addr.IPNet = local
@@ -357,7 +357,8 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -372,7 +373,6 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
diff --git a/vendor/github.com/vishvananda/netlink/bpf_linux.go b/vendor/github.com/vishvananda/netlink/bpf_linux.go
index 6631626bf..96befbfe0 100644
--- a/vendor/github.com/vishvananda/netlink/bpf_linux.go
+++ b/vendor/github.com/vishvananda/netlink/bpf_linux.go
@@ -16,6 +16,30 @@ const (
BPF_PROG_TYPE_SCHED_ACT
BPF_PROG_TYPE_TRACEPOINT
BPF_PROG_TYPE_XDP
+ BPF_PROG_TYPE_PERF_EVENT
+ BPF_PROG_TYPE_CGROUP_SKB
+ BPF_PROG_TYPE_CGROUP_SOCK
+ BPF_PROG_TYPE_LWT_IN
+ BPF_PROG_TYPE_LWT_OUT
+ BPF_PROG_TYPE_LWT_XMIT
+ BPF_PROG_TYPE_SOCK_OPS
+ BPF_PROG_TYPE_SK_SKB
+ BPF_PROG_TYPE_CGROUP_DEVICE
+ BPF_PROG_TYPE_SK_MSG
+ BPF_PROG_TYPE_RAW_TRACEPOINT
+ BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+ BPF_PROG_TYPE_LWT_SEG6LOCAL
+ BPF_PROG_TYPE_LIRC_MODE2
+ BPF_PROG_TYPE_SK_REUSEPORT
+ BPF_PROG_TYPE_FLOW_DISSECTOR
+ BPF_PROG_TYPE_CGROUP_SYSCTL
+ BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
+ BPF_PROG_TYPE_CGROUP_SOCKOPT
+ BPF_PROG_TYPE_TRACING
+ BPF_PROG_TYPE_STRUCT_OPS
+ BPF_PROG_TYPE_EXT
+ BPF_PROG_TYPE_LSM
+ BPF_PROG_TYPE_SK_LOOKUP
)
type BPFAttr struct {
diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go
index 029568a3f..6f542ba4e 100644
--- a/vendor/github.com/vishvananda/netlink/class_linux.go
+++ b/vendor/github.com/vishvananda/netlink/class_linux.go
@@ -191,9 +191,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
opt.Fsc.Set(fm1/8, fd, fm2/8)
um1, ud, um2 := hfsc.Usc.Attrs()
opt.Usc.Set(um1/8, ud, um2/8)
- nl.NewRtAttrChild(options, nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
- nl.NewRtAttrChild(options, nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
- nl.NewRtAttrChild(options, nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
+ options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
+ options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
+ options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
}
req.AddData(options)
return nil
@@ -341,7 +341,6 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err
func parseTcStats(data []byte) (*ClassStatistics, error) {
buf := &bytes.Buffer{}
buf.Write(data)
- native := nl.NativeEndian()
tcStats := &tcStats{}
if err := binary.Read(buf, native, tcStats); err != nil {
return nil, err
@@ -363,7 +362,6 @@ func parseTcStats(data []byte) (*ClassStatistics, error) {
func parseGnetStats(data []byte, gnetStats interface{}) error {
buf := &bytes.Buffer{}
buf.Write(data)
- native := nl.NativeEndian()
return binary.Read(buf, native, gnetStats)
}
diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
index ab91f4e55..03ea1b98f 100644
--- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
+ "time"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
@@ -145,16 +146,23 @@ type ConntrackFlow struct {
Forward ipTuple
Reverse ipTuple
Mark uint32
+ TimeStart uint64
+ TimeStop uint64
+ TimeOut uint32
}
func (s *ConntrackFlow) String() string {
// conntrack cmd output:
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
- return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d",
+ // start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
+ start := time.Unix(0, int64(s.TimeStart))
+ stop := time.Unix(0, int64(s.TimeStop))
+ timeout := int32(s.TimeOut)
+ return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x start=%v stop=%v timeout=%d(sec)",
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
- s.Mark)
+ s.Mark, start, stop, timeout)
}
// This method parse the ip tuple structure
@@ -174,25 +182,43 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
tpl.DstIP = v
}
}
- // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO
- reader.Seek(4, seekCurrent)
- _, t, _, v := parseNfAttrTLV(reader)
+ // Get total length of nested protocol-specific info.
+ _, _, protoInfoTotalLen := parseNfAttrTL(reader)
+ _, t, l, v := parseNfAttrTLV(reader)
+ // Track the number of bytes read.
+ protoInfoBytesRead := uint16(nl.SizeofNfattr) + l
if t == nl.CTA_PROTO_NUM {
tpl.Protocol = uint8(v[0])
}
- // Skip some padding 3 bytes
+ // We only parse TCP & UDP headers. Skip the others.
+ if tpl.Protocol != 6 && tpl.Protocol != 17 {
+ // skip the rest
+ bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
+ reader.Seek(int64(bytesRemaining), seekCurrent)
+ return tpl.Protocol
+ }
+ // Skip 3 bytes of padding
reader.Seek(3, seekCurrent)
+ protoInfoBytesRead += 3
for i := 0; i < 2; i++ {
_, t, _ := parseNfAttrTL(reader)
+ protoInfoBytesRead += uint16(nl.SizeofNfattr)
switch t {
case nl.CTA_PROTO_SRC_PORT:
parseBERaw16(reader, &tpl.SrcPort)
+ protoInfoBytesRead += 2
case nl.CTA_PROTO_DST_PORT:
parseBERaw16(reader, &tpl.DstPort)
+ protoInfoBytesRead += 2
}
- // Skip some padding 2 byte
+ // Skip 2 bytes of padding
reader.Seek(2, seekCurrent)
+ protoInfoBytesRead += 2
}
+ // Skip any remaining/unknown parts of the message
+ bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
+ reader.Seek(int64(bytesRemaining), seekCurrent)
+
return tpl.Protocol
}
@@ -211,10 +237,14 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
binary.Read(r, nl.NativeEndian(), &attrType)
isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED
attrType = attrType & (nl.NLA_F_NESTED - 1)
-
return isNested, attrType, len
}
+func skipNfAttrValue(r *bytes.Reader, len uint16) {
+ len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
+ r.Seek(int64(len), seekCurrent)
+}
+
func parseBERaw16(r *bytes.Reader, v *uint16) {
binary.Read(r, binary.BigEndian, v)
}
@@ -241,6 +271,36 @@ func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
return
}
+// when the flow is alive, only the timestamp_start is returned in structure
+func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
+ var numTimeStamps int
+ oneItem := nl.SizeofNfattr + 8 // 4 bytes attr header + 8 bytes timestamp
+ if readSize == uint16(oneItem) {
+ numTimeStamps = 1
+ } else if readSize == 2*uint16(oneItem) {
+ numTimeStamps = 2
+ } else {
+ return
+ }
+ for i := 0; i < numTimeStamps; i++ {
+ switch _, t, _ := parseNfAttrTL(r); t {
+ case nl.CTA_TIMESTAMP_START:
+ parseBERaw64(r, &tstart)
+ case nl.CTA_TIMESTAMP_STOP:
+ parseBERaw64(r, &tstop)
+ default:
+ return
+ }
+ }
+ return
+
+}
+
+func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
+ parseBERaw32(r, &ttimeout)
+ return
+}
+
func parseConnectionMark(r *bytes.Reader) (mark uint32) {
parseBERaw32(r, &mark)
return
@@ -266,25 +326,37 @@ func parseRawData(data []byte) *ConntrackFlow {
if nested, t, l := parseNfAttrTL(reader); nested {
switch t {
case nl.CTA_TUPLE_ORIG:
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
parseIpTuple(reader, &s.Forward)
}
case nl.CTA_TUPLE_REPLY:
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
parseIpTuple(reader, &s.Reverse)
} else {
// Header not recognized skip it
- reader.Seek(int64(l), seekCurrent)
+ skipNfAttrValue(reader, l)
}
case nl.CTA_COUNTERS_ORIG:
s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader)
case nl.CTA_COUNTERS_REPLY:
s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
+ case nl.CTA_TIMESTAMP:
+ s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
+ case nl.CTA_PROTOINFO:
+ skipNfAttrValue(reader, l)
+ default:
+ skipNfAttrValue(reader, l)
}
} else {
switch t {
case nl.CTA_MARK:
s.Mark = parseConnectionMark(reader)
+ case nl.CTA_TIMEOUT:
+ s.TimeOut = parseTimeOut(reader)
+ case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
+ skipNfAttrValue(reader, l)
+ default:
+ skipNfAttrValue(reader, l)
}
}
}
@@ -346,23 +418,34 @@ type CustomConntrackFilter interface {
}
type ConntrackFilter struct {
- ipFilter map[ConntrackFilterType]net.IP
+ ipNetFilter map[ConntrackFilterType]*net.IPNet
portFilter map[ConntrackFilterType]uint16
protoFilter uint8
}
-// AddIP adds an IP to the conntrack filter
-func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
- if f.ipFilter == nil {
- f.ipFilter = make(map[ConntrackFilterType]net.IP)
+// AddIPNet adds a IP subnet to the conntrack filter
+func (f *ConntrackFilter) AddIPNet(tp ConntrackFilterType, ipNet *net.IPNet) error {
+ if ipNet == nil {
+ return fmt.Errorf("Filter attribute empty")
}
- if _, ok := f.ipFilter[tp]; ok {
+ if f.ipNetFilter == nil {
+ f.ipNetFilter = make(map[ConntrackFilterType]*net.IPNet)
+ }
+ if _, ok := f.ipNetFilter[tp]; ok {
return errors.New("Filter attribute already present")
}
- f.ipFilter[tp] = ip
+ f.ipNetFilter[tp] = ipNet
return nil
}
+// AddIP adds an IP to the conntrack filter
+func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
+ if ip == nil {
+ return fmt.Errorf("Filter attribute empty")
+ }
+ return f.AddIPNet(tp, NewIPNet(ip))
+}
+
// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it
func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error {
switch f.protoFilter {
@@ -394,7 +477,7 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
// false otherwise
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
- if len(f.ipFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
+ if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
// empty filter always not match
return false
}
@@ -408,30 +491,30 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
match := true
// IP conntrack filter
- if len(f.ipFilter) > 0 {
+ if len(f.ipNetFilter) > 0 {
// -orig-src ip Source address from original direction
- if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found {
- match = match && elem.Equal(flow.Forward.SrcIP)
+ if elem, found := f.ipNetFilter[ConntrackOrigSrcIP]; found {
+ match = match && elem.Contains(flow.Forward.SrcIP)
}
// -orig-dst ip Destination address from original direction
- if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found {
- match = match && elem.Equal(flow.Forward.DstIP)
+ if elem, found := f.ipNetFilter[ConntrackOrigDstIP]; match && found {
+ match = match && elem.Contains(flow.Forward.DstIP)
}
// -src-nat ip Source NAT ip
- if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found {
- match = match && elem.Equal(flow.Reverse.SrcIP)
+ if elem, found := f.ipNetFilter[ConntrackReplySrcIP]; match && found {
+ match = match && elem.Contains(flow.Reverse.SrcIP)
}
// -dst-nat ip Destination NAT ip
- if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found {
- match = match && elem.Equal(flow.Reverse.DstIP)
+ if elem, found := f.ipNetFilter[ConntrackReplyDstIP]; match && found {
+ match = match && elem.Contains(flow.Reverse.DstIP)
}
// Match source or destination reply IP
- if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
- match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
+ if elem, found := f.ipNetFilter[ConntrackReplyAnyIP]; match && found {
+ match = match && (elem.Contains(flow.Reverse.SrcIP) || elem.Contains(flow.Reverse.DstIP))
}
}
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
index 7d57080e8..358b232c6 100644
--- a/vendor/github.com/vishvananda/netlink/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -1,9 +1,11 @@
package netlink
import (
+ "fmt"
+ "net"
+ "strings"
"syscall"
- "fmt"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
@@ -27,6 +29,20 @@ type DevlinkDevice struct {
Attrs DevlinkDevAttrs
}
+// DevlinkPortFn represents port function and its attributes
+type DevlinkPortFn struct {
+ HwAddr net.HardwareAddr
+ State uint8
+ OpState uint8
+}
+
+// DevlinkPortFnSetAttrs represents attributes to set
+type DevlinkPortFnSetAttrs struct {
+ FnAttrs DevlinkPortFn
+ HwAddrValid bool
+ StateValid bool
+}
+
// DevlinkPort represents port and its attributes
type DevlinkPort struct {
BusName string
@@ -37,6 +53,35 @@ type DevlinkPort struct {
NetdevIfIndex uint32
RdmaDeviceName string
PortFlavour uint16
+ Fn *DevlinkPortFn
+}
+
+type DevLinkPortAddAttrs struct {
+ Controller uint32
+ SfNumber uint32
+ PortIndex uint32
+ PfNumber uint16
+ SfNumberValid bool
+ PortIndexValid bool
+ ControllerValid bool
+}
+
+// DevlinkDeviceInfo represents devlink info
+type DevlinkDeviceInfo struct {
+ Driver string
+ SerialNumber string
+ BoardID string
+ FwApp string
+ FwAppBoundleID string
+ FwAppName string
+ FwBoundleID string
+ FwMgmt string
+ FwMgmtAPI string
+ FwMgmtBuild string
+ FwNetlist string
+ FwNetlistBuild string
+ FwPsidAPI string
+ FwUndi string
}
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
@@ -107,9 +152,9 @@ func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
for _, a := range attrs {
switch a.Attr.Type {
case nl.DEVLINK_ATTR_BUS_NAME:
- d.BusName = string(a.Value)
+ d.BusName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_DEV_NAME:
- d.DeviceName = string(a.Value)
+ d.DeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_ESWITCH_MODE:
d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
@@ -138,12 +183,12 @@ func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
req.AddData(msg)
- b := make([]byte, len(dev.BusName))
+ b := make([]byte, len(dev.BusName)+1)
copy(b, dev.BusName)
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
req.AddData(data)
- b = make([]byte, len(dev.DeviceName))
+ b = make([]byte, len(dev.DeviceName)+1)
copy(b, dev.DeviceName)
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
req.AddData(data)
@@ -287,21 +332,33 @@ func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
for _, a := range attrs {
switch a.Attr.Type {
case nl.DEVLINK_ATTR_BUS_NAME:
- port.BusName = string(a.Value)
+ port.BusName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_DEV_NAME:
- port.DeviceName = string(a.Value)
+ port.DeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_INDEX:
port.PortIndex = native.Uint32(a.Value)
case nl.DEVLINK_ATTR_PORT_TYPE:
port.PortType = native.Uint16(a.Value)
case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
- port.NetdeviceName = string(a.Value)
+ port.NetdeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
port.NetdevIfIndex = native.Uint32(a.Value)
case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
- port.RdmaDeviceName = string(a.Value)
+ port.RdmaDeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_FLAVOUR:
port.PortFlavour = native.Uint16(a.Value)
+ case nl.DEVLINK_ATTR_PORT_FUNCTION:
+ port.Fn = &DevlinkPortFn{}
+ for nested := range nl.ParseAttributes(a.Value) {
+ switch nested.Type {
+ case nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR:
+ port.Fn.HwAddr = nested.Value[:]
+ case nl.DEVLINK_PORT_FN_ATTR_STATE:
+ port.Fn.State = uint8(nested.Value[0])
+ case nl.DEVLINK_PORT_FN_ATTR_OPSTATE:
+ port.Fn.OpState = uint8(nested.Value[0])
+ }
+ }
}
}
return nil
@@ -391,3 +448,281 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
}
+
+// DevLinkPortAdd adds a devlink port and returns a port on success
+// otherwise returns nil port and an error code.
+func (h *Handle) DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_NEW, Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FLAVOUR, nl.Uint16Attr(Flavour)))
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_PF_NUMBER, nl.Uint16Attr(Attrs.PfNumber)))
+ if Flavour == nl.DEVLINK_PORT_FLAVOUR_PCI_SF && Attrs.SfNumberValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_SF_NUMBER, nl.Uint32Attr(Attrs.SfNumber)))
+ }
+ if Attrs.PortIndexValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(Attrs.PortIndex)))
+ }
+ if Attrs.ControllerValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, nl.Uint32Attr(Attrs.Controller)))
+ }
+ respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ port, err := parseDevlinkPortMsg(respmsg)
+ return port, err
+}
+
+// DevLinkPortAdd adds a devlink port and returns a port on success
+// otherwise returns nil port and an error code.
+func DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
+ return pkgHandle.DevLinkPortAdd(Bus, Device, Flavour, Attrs)
+}
+
+// DevLinkPortDel deletes a devlink port and returns success or error code.
+func (h *Handle) DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_DEL, Bus, Device)
+ if err != nil {
+ return err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+ _, err = req.Execute(unix.NETLINK_GENERIC, 0)
+ return err
+}
+
+// DevLinkPortDel deletes a devlink port and returns success or error code.
+func DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
+ return pkgHandle.DevLinkPortDel(Bus, Device, PortIndex)
+}
+
+// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
+// It returns 0 on success or error code.
+func (h *Handle) DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_SET, Bus, Device)
+ if err != nil {
+ return err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+
+ fnAttr := nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FUNCTION|unix.NLA_F_NESTED, nil)
+
+ if FnAttrs.HwAddrValid {
+ fnAttr.AddRtAttr(nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, []byte(FnAttrs.FnAttrs.HwAddr))
+ }
+
+ if FnAttrs.StateValid {
+ fnAttr.AddRtAttr(nl.DEVLINK_PORT_FN_ATTR_STATE, nl.Uint8Attr(FnAttrs.FnAttrs.State))
+ }
+ req.AddData(fnAttr)
+
+ _, err = req.Execute(unix.NETLINK_GENERIC, 0)
+ return err
+}
+
+// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
+// It returns 0 on success or error code.
+func DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
+ return pkgHandle.DevlinkPortFnSet(Bus, Device, PortIndex, FnAttrs)
+}
+
+// devlinkInfoGetter is function that is responsible for getting devlink info message
+// this is introduced for test purpose
+type devlinkInfoGetter func(bus, device string) ([]byte, error)
+
+// DevlinkGetDeviceInfoByName returns devlink info for selected device,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func (h *Handle) DevlinkGetDeviceInfoByName(Bus string, Device string, getInfoMsg devlinkInfoGetter) (*DevlinkDeviceInfo, error) {
+ info, err := h.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, getInfoMsg)
+ if err != nil {
+ return nil, err
+ }
+
+ return parseInfoData(info), nil
+}
+
+// DevlinkGetDeviceInfoByName returns devlink info for selected device,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func DevlinkGetDeviceInfoByName(Bus string, Device string) (*DevlinkDeviceInfo, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByName(Bus, Device, pkgHandle.getDevlinkInfoMsg)
+}
+
+// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func (h *Handle) DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string, getInfoMsg devlinkInfoGetter) (map[string]string, error) {
+ response, err := getInfoMsg(Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := parseInfoMsg(response)
+ if err != nil {
+ return nil, err
+ }
+
+ return info, nil
+}
+
+// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string) (map[string]string, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, pkgHandle.getDevlinkInfoMsg)
+}
+
+// GetDevlinkInfo returns devlink info for target device,
+// otherwise returns an error code.
+func (d *DevlinkDevice) GetDevlinkInfo() (*DevlinkDeviceInfo, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByName(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
+}
+
+// GetDevlinkInfoAsMap returns devlink info for target device as a map,
+// otherwise returns an error code.
+func (d *DevlinkDevice) GetDevlinkInfoAsMap() (map[string]string, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
+}
+
+func (h *Handle) getDevlinkInfoMsg(bus, device string) ([]byte, error) {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_INFO_GET, bus, device)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(response) < 1 {
+ return nil, fmt.Errorf("getDevlinkInfoMsg: message too short")
+ }
+
+ return response[0], nil
+}
+
+func parseInfoMsg(msg []byte) (map[string]string, error) {
+ if len(msg) < nl.SizeofGenlmsg {
+ return nil, fmt.Errorf("parseInfoMsg: message too short")
+ }
+
+ info := make(map[string]string)
+ err := collectInfoData(msg[nl.SizeofGenlmsg:], info)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return info, nil
+}
+
+func collectInfoData(msg []byte, data map[string]string) error {
+ attrs, err := nl.ParseRouteAttr(msg)
+ if err != nil {
+ return err
+ }
+
+ for _, attr := range attrs {
+ switch attr.Attr.Type {
+ case nl.DEVLINK_ATTR_INFO_DRIVER_NAME:
+ data["driver"] = parseInfoValue(attr.Value)
+ case nl.DEVLINK_ATTR_INFO_SERIAL_NUMBER:
+ data["serialNumber"] = parseInfoValue(attr.Value)
+ case nl.DEVLINK_ATTR_INFO_VERSION_RUNNING, nl.DEVLINK_ATTR_INFO_VERSION_FIXED,
+ nl.DEVLINK_ATTR_INFO_VERSION_STORED:
+ key, value, err := getNestedInfoData(attr.Value)
+ if err != nil {
+ return err
+ }
+ data[key] = value
+ }
+ }
+
+ if len(data) == 0 {
+ return fmt.Errorf("collectInfoData: could not read attributes")
+ }
+
+ return nil
+}
+
+func getNestedInfoData(msg []byte) (string, string, error) {
+ nestedAttrs, err := nl.ParseRouteAttr(msg)
+
+ var key, value string
+
+ if err != nil {
+ return "", "", err
+ }
+
+ if len(nestedAttrs) != 2 {
+ return "", "", fmt.Errorf("getNestedInfoData: too few attributes in nested structure")
+ }
+
+ for _, nestedAttr := range nestedAttrs {
+ switch nestedAttr.Attr.Type {
+ case nl.DEVLINK_ATTR_INFO_VERSION_NAME:
+ key = parseInfoValue(nestedAttr.Value)
+ case nl.DEVLINK_ATTR_INFO_VERSION_VALUE:
+ value = parseInfoValue(nestedAttr.Value)
+ }
+ }
+
+ if key == "" {
+ return "", "", fmt.Errorf("getNestedInfoData: key not found")
+ }
+
+ if value == "" {
+ return "", "", fmt.Errorf("getNestedInfoData: value not found")
+ }
+
+ return key, value, nil
+}
+
+func parseInfoData(data map[string]string) *DevlinkDeviceInfo {
+ info := new(DevlinkDeviceInfo)
+ for key, value := range data {
+ switch key {
+ case "driver":
+ info.Driver = value
+ case "serialNumber":
+ info.SerialNumber = value
+ case "board.id":
+ info.BoardID = value
+ case "fw.app":
+ info.FwApp = value
+ case "fw.app.bundle_id":
+ info.FwAppBoundleID = value
+ case "fw.app.name":
+ info.FwAppName = value
+ case "fw.bundle_id":
+ info.FwBoundleID = value
+ case "fw.mgmt":
+ info.FwMgmt = value
+ case "fw.mgmt.api":
+ info.FwMgmtAPI = value
+ case "fw.mgmt.build":
+ info.FwMgmtBuild = value
+ case "fw.netlist":
+ info.FwNetlist = value
+ case "fw.netlist.build":
+ info.FwNetlistBuild = value
+ case "fw.psid.api":
+ info.FwPsidAPI = value
+ case "fw.undi":
+ info.FwUndi = value
+ }
+ }
+ return info
+}
+
+func parseInfoValue(value []byte) string {
+ v := strings.ReplaceAll(string(value), "\x00", "")
+ return strings.TrimSpace(v)
+}
diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go
index 2dc34b995..413abdb47 100644
--- a/vendor/github.com/vishvananda/netlink/filter.go
+++ b/vendor/github.com/vishvananda/netlink/filter.go
@@ -260,6 +260,40 @@ func NewSkbEditAction() *SkbEditAction {
}
}
+type PoliceAction struct {
+ ActionAttrs
+ Rate uint32 // in byte per second
+ Burst uint32 // in byte
+ RCellLog int
+ Mtu uint32
+ Mpu uint16 // in byte
+ PeakRate uint32 // in byte per second
+ PCellLog int
+ AvRate uint32 // in byte per second
+ Overhead uint16
+ LinkLayer int
+ ExceedAction TcPolAct
+ NotExceedAction TcPolAct
+}
+
+func (action *PoliceAction) Type() string {
+ return "police"
+}
+
+func (action *PoliceAction) Attrs() *ActionAttrs {
+ return &action.ActionAttrs
+}
+
+func NewPoliceAction() *PoliceAction {
+ return &PoliceAction{
+ RCellLog: -1,
+ PCellLog: -1,
+ LinkLayer: 1, // ETHERNET
+ ExceedAction: TC_POLICE_RECLASSIFY,
+ NotExceedAction: TC_POLICE_OK,
+ }
+}
+
// MatchAll filters match all packets
type MatchAll struct {
FilterAttrs
@@ -275,20 +309,20 @@ func (filter *MatchAll) Type() string {
return "matchall"
}
-type FilterFwAttrs struct {
- ClassId uint32
- InDev string
- Mask uint32
- Index uint32
- Buffer uint32
- Mtu uint32
- Mpu uint16
- Rate uint32
- AvRate uint32
- PeakRate uint32
- Action TcPolAct
- Overhead uint16
- LinkLayer int
+type FwFilter struct {
+ FilterAttrs
+ ClassId uint32
+ InDev string
+ Mask uint32
+ Police *PoliceAction
+}
+
+func (filter *FwFilter) Attrs() *FilterAttrs {
+ return &filter.FilterAttrs
+}
+
+func (filter *FwFilter) Type() string {
+ return "fw"
}
type BpfFilter struct {
diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go
index 2cd46266c..3cfea4586 100644
--- a/vendor/github.com/vishvananda/netlink/filter_linux.go
+++ b/vendor/github.com/vishvananda/netlink/filter_linux.go
@@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
+ "net"
"syscall"
"github.com/vishvananda/netlink/nl"
@@ -50,74 +51,129 @@ func (filter *U32) Type() string {
return "u32"
}
-// Fw filter filters on firewall marks
-// NOTE: this is in filter_linux because it refers to nl.TcPolice which
-// is defined in nl/tc_linux.go
-type Fw struct {
+type Flower struct {
FilterAttrs
- ClassId uint32
- // TODO remove nl type from interface
- Police nl.TcPolice
- InDev string
- // TODO Action
- Mask uint32
- AvRate uint32
- Rtab [256]uint32
- Ptab [256]uint32
-}
-
-func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
- var rtab [256]uint32
- var ptab [256]uint32
- rcellLog := -1
- pcellLog := -1
- avrate := fattrs.AvRate / 8
- police := nl.TcPolice{}
- police.Rate.Rate = fattrs.Rate / 8
- police.PeakRate.Rate = fattrs.PeakRate / 8
- buffer := fattrs.Buffer
- linklayer := nl.LINKLAYER_ETHERNET
+ DestIP net.IP
+ DestIPMask net.IPMask
+ SrcIP net.IP
+ SrcIPMask net.IPMask
+ EthType uint16
+ EncDestIP net.IP
+ EncDestIPMask net.IPMask
+ EncSrcIP net.IP
+ EncSrcIPMask net.IPMask
+ EncDestPort uint16
+ EncKeyId uint32
+
+ Actions []Action
+}
- if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC {
- linklayer = fattrs.LinkLayer
- }
+func (filter *Flower) Attrs() *FilterAttrs {
+ return &filter.FilterAttrs
+}
- police.Action = int32(fattrs.Action)
- if police.Rate.Rate != 0 {
- police.Rate.Mpu = fattrs.Mpu
- police.Rate.Overhead = fattrs.Overhead
- if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
- return nil, errors.New("TBF: failed to calculate rate table")
- }
- police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer))
+func (filter *Flower) Type() string {
+ return "flower"
+}
+
+func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
+ ipType := v4Type
+ maskType := v4MaskType
+
+ encodeMask := mask
+ if mask == nil {
+ encodeMask = net.CIDRMask(32, 32)
}
- police.Mtu = fattrs.Mtu
- if police.PeakRate.Rate != 0 {
- police.PeakRate.Mpu = fattrs.Mpu
- police.PeakRate.Overhead = fattrs.Overhead
- if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
- return nil, errors.New("POLICE: failed to calculate peak rate table")
- }
+ v4IP := ip.To4()
+ if v4IP == nil {
+ ipType = v6Type
+ maskType = v6MaskType
+ if mask == nil {
+ encodeMask = net.CIDRMask(128, 128)
+ }
+ } else {
+ ip = v4IP
}
- return &Fw{
- FilterAttrs: attrs,
- ClassId: fattrs.ClassId,
- InDev: fattrs.InDev,
- Mask: fattrs.Mask,
- Police: police,
- AvRate: avrate,
- Rtab: rtab,
- Ptab: ptab,
- }, nil
+ parent.AddRtAttr(ipType, ip)
+ parent.AddRtAttr(maskType, encodeMask)
}
-func (filter *Fw) Attrs() *FilterAttrs {
- return &filter.FilterAttrs
+func (filter *Flower) encode(parent *nl.RtAttr) error {
+ if filter.EthType != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
+ }
+ if filter.SrcIP != nil {
+ filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
+ nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
+ nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
+ }
+ if filter.DestIP != nil {
+ filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
+ nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
+ nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
+ }
+ if filter.EncSrcIP != nil {
+ filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
+ }
+ if filter.EncDestIP != nil {
+ filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
+ }
+ if filter.EncDestPort != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
+ }
+ if filter.EncKeyId != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
+ }
+
+ actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
+ if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
+ return err
+ }
+ return nil
}
-func (filter *Fw) Type() string {
- return "fw"
+func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.TCA_FLOWER_KEY_ETH_TYPE:
+ filter.EthType = ntohs(datum.Value)
+ case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
+ filter.SrcIP = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
+ filter.SrcIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
+ filter.DestIP = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
+ filter.DestIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
+ filter.EncSrcIP = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
+ filter.EncSrcIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
+ filter.EncDestIP = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
+ filter.EncDestIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
+ filter.EncDestPort = ntohs(datum.Value)
+ case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
+ filter.EncKeyId = ntohl(datum.Value)
+ case nl.TCA_FLOWER_ACT:
+ tables, err := nl.ParseRouteAttr(datum.Value)
+ if err != nil {
+ return err
+ }
+ filter.Actions, err = parseActions(tables)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
}
// FilterDel will delete a filter from the system.
@@ -169,7 +225,6 @@ func (h *Handle) FilterReplace(filter Filter) error {
}
func (h *Handle) filterModify(filter Filter, flags int) error {
- native = nl.NativeEndian()
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
@@ -237,7 +292,7 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
return err
}
- case *Fw:
+ case *FwFilter:
if filter.Mask != 0 {
b := make([]byte, 4)
native.PutUint32(b, filter.Mask)
@@ -246,17 +301,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.InDev != "" {
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
}
- if (filter.Police != nl.TcPolice{}) {
-
+ if filter.Police != nil {
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
- police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
- if (filter.Police.Rate != nl.TcRateSpec{}) {
- payload := SerializeRtab(filter.Rtab)
- police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
- }
- if (filter.Police.PeakRate != nl.TcRateSpec{}) {
- payload := SerializeRtab(filter.Ptab)
- police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
+ if err := encodePolice(police, filter.Police); err != nil {
+ return err
}
}
if filter.ClassId != 0 {
@@ -287,6 +335,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.ClassId != 0 {
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
}
+ case *Flower:
+ if err := filter.encode(options); err != nil {
+ return err
+ }
}
req.AddData(options)
@@ -350,11 +402,13 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
case "u32":
filter = &U32{}
case "fw":
- filter = &Fw{}
+ filter = &FwFilter{}
case "bpf":
filter = &BpfFilter{}
case "matchall":
filter = &MatchAll{}
+ case "flower":
+ filter = &Flower{}
default:
filter = &GenericFilter{FilterType: filterType}
}
@@ -384,6 +438,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
if err != nil {
return nil, err
}
+ case "flower":
+ detailed, err = parseFlowerData(filter, data)
+ if err != nil {
+ return nil, err
+ }
default:
detailed = true
}
@@ -415,6 +474,53 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
attrs.Bindcnt = int(tcgen.Bindcnt)
}
+func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
+ var rtab [256]uint32
+ var ptab [256]uint32
+ police := nl.TcPolice{}
+ police.Index = uint32(action.Attrs().Index)
+ police.Bindcnt = int32(action.Attrs().Bindcnt)
+ police.Capab = uint32(action.Attrs().Capab)
+ police.Refcnt = int32(action.Attrs().Refcnt)
+ police.Rate.Rate = action.Rate
+ police.PeakRate.Rate = action.PeakRate
+ police.Action = int32(action.ExceedAction)
+
+ if police.Rate.Rate != 0 {
+ police.Rate.Mpu = action.Mpu
+ police.Rate.Overhead = action.Overhead
+ if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
+ return errors.New("TBF: failed to calculate rate table")
+ }
+ police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
+ }
+
+ police.Mtu = action.Mtu
+ if police.PeakRate.Rate != 0 {
+ police.PeakRate.Mpu = action.Mpu
+ police.PeakRate.Overhead = action.Overhead
+ if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
+ return errors.New("POLICE: failed to calculate peak rate table")
+ }
+ }
+
+ attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
+ if police.Rate.Rate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
+ }
+ if police.PeakRate.Rate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
+ }
+ if action.AvRate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
+ }
+ if action.NotExceedAction != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
+ }
+
+ return nil
+}
+
func EncodeActions(attr *nl.RtAttr, actions []Action) error {
tabIndex := int(nl.TCA_ACT_TAB)
@@ -422,6 +528,14 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
switch action := action.(type) {
default:
return fmt.Errorf("unknown action type %s", action.Type())
+ case *PoliceAction:
+ table := attr.AddRtAttr(tabIndex, nil)
+ tabIndex++
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
+ if err := encodePolice(aopts, action); err != nil {
+ return err
+ }
case *MirredAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
@@ -516,6 +630,29 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
return nil
}
+func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
+ switch data.Attr.Type {
+ case nl.TCA_POLICE_RESULT:
+ police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
+ case nl.TCA_POLICE_AVRATE:
+ police.AvRate = native.Uint32(data.Value[0:4])
+ case nl.TCA_POLICE_TBF:
+ p := *nl.DeserializeTcPolice(data.Value)
+ police.ActionAttrs = ActionAttrs{}
+ police.Attrs().Index = int(p.Index)
+ police.Attrs().Bindcnt = int(p.Bindcnt)
+ police.Attrs().Capab = int(p.Capab)
+ police.Attrs().Refcnt = int(p.Refcnt)
+ police.ExceedAction = TcPolAct(p.Action)
+ police.Rate = p.Rate.Rate
+ police.PeakRate = p.PeakRate.Rate
+ police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
+ police.Mtu = p.Mtu
+ police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
+ police.Overhead = p.Rate.Overhead
+ }
+}
+
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
var actions []Action
for _, table := range tables {
@@ -544,6 +681,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &TunnelKeyAction{}
case "skbedit":
action = &SkbEditAction{}
+ case "police":
+ action = &PoliceAction{}
default:
break nextattr
}
@@ -622,6 +761,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
gen := *nl.DeserializeTcGen(adatum.Value)
toAttrs(&gen, action.Attrs())
}
+ case "police":
+ parsePolice(adatum, action.(*PoliceAction))
}
}
}
@@ -632,7 +773,6 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
}
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
u32 := filter.(*U32)
detailed := false
for _, datum := range data {
@@ -678,8 +818,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
}
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
- fw := filter.(*Fw)
+ fw := filter.(*FwFilter)
detailed := true
for _, datum := range data {
switch datum.Attr.Type {
@@ -690,24 +829,18 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
case nl.TCA_FW_INDEV:
fw.InDev = string(datum.Value[:len(datum.Value)-1])
case nl.TCA_FW_POLICE:
+ var police PoliceAction
adata, _ := nl.ParseRouteAttr(datum.Value)
for _, aattr := range adata {
- switch aattr.Attr.Type {
- case nl.TCA_POLICE_TBF:
- fw.Police = *nl.DeserializeTcPolice(aattr.Value)
- case nl.TCA_POLICE_RATE:
- fw.Rtab = DeserializeRtab(aattr.Value)
- case nl.TCA_POLICE_PEAKRATE:
- fw.Ptab = DeserializeRtab(aattr.Value)
- }
+ parsePolice(aattr, &police)
}
+ fw.Police = &police
}
}
return detailed, nil
}
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
bpf := filter.(*BpfFilter)
detailed := true
for _, datum := range data {
@@ -733,7 +866,6 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
}
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
matchall := filter.(*MatchAll)
detailed := true
for _, datum := range data {
@@ -754,6 +886,10 @@ func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, er
return detailed, nil
}
+func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
+ return true, filter.(*Flower).decode(data)
+}
+
func AlignToAtm(size uint) uint {
var linksize, cells int
cells = int(size / nl.ATM_CELL_PAYLOAD)
@@ -801,14 +937,12 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin
func DeserializeRtab(b []byte) [256]uint32 {
var rtab [256]uint32
- native := nl.NativeEndian()
r := bytes.NewReader(b)
_ = binary.Read(r, native, &rtab)
return rtab
}
func SerializeRtab(rtab [256]uint32) []byte {
- native := nl.NativeEndian()
var w bytes.Buffer
_ = binary.Write(&w, native, rtab)
return w.Bytes()
diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go
index 65356679d..c02bfb7e6 100644
--- a/vendor/github.com/vishvananda/netlink/handle_linux.go
+++ b/vendor/github.com/vishvananda/netlink/handle_linux.go
@@ -15,7 +15,7 @@ var pkgHandle = &Handle{}
// Handle is an handle for the netlink requests on a
// specific network namespace. All the requests on the
// same netlink family share the same netlink socket,
-// which gets released when the handle is deleted.
+// which gets released when the handle is Close'd.
type Handle struct {
sockets map[int]*nl.SocketHandle
lookupByDump bool
@@ -136,14 +136,22 @@ func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error)
return h, nil
}
-// Delete releases the resources allocated to this handle
-func (h *Handle) Delete() {
+// Close releases the resources allocated to this handle
+func (h *Handle) Close() {
for _, sh := range h.sockets {
sh.Close()
}
h.sockets = nil
}
+// Delete releases the resources allocated to this handle
+//
+// Deprecated: use Close instead which is in line with typical resource release
+// patterns for files and other resources.
+func (h *Handle) Delete() {
+ h.Close()
+}
+
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
// Do this so that package API still use nl package variable nextSeqNr
if h.sockets == nil {
diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
index 3a6db8137..cc94a4e00 100644
--- a/vendor/github.com/vishvananda/netlink/handle_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
@@ -23,6 +23,8 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
return nil, ErrNotImplemented
}
+func (h *Handle) Close() {}
+
func (h *Handle) Delete() {}
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
diff --git a/vendor/github.com/vishvananda/netlink/ipset_linux.go b/vendor/github.com/vishvananda/netlink/ipset_linux.go
index 2adc2440a..1f4eae81c 100644
--- a/vendor/github.com/vishvananda/netlink/ipset_linux.go
+++ b/vendor/github.com/vishvananda/netlink/ipset_linux.go
@@ -1,6 +1,7 @@
package netlink
import (
+ "encoding/binary"
"log"
"net"
"syscall"
@@ -11,12 +12,19 @@ import (
// IPSetEntry is used for adding, updating, retreiving and deleting entries
type IPSetEntry struct {
- Comment string
- MAC net.HardwareAddr
- IP net.IP
- Timeout *uint32
- Packets *uint64
- Bytes *uint64
+ Comment string
+ MAC net.HardwareAddr
+ IP net.IP
+ CIDR uint8
+ Timeout *uint32
+ Packets *uint64
+ Bytes *uint64
+ Protocol *uint8
+ Port *uint16
+ IP2 net.IP
+ CIDR2 uint8
+ IFace string
+ Mark *uint32
Replace bool // replace existing entry
}
@@ -32,6 +40,12 @@ type IPSetResult struct {
SetName string
TypeName string
Comment string
+ MarkMask uint32
+
+ IPFrom net.IP
+ IPTo net.IP
+ PortFrom uint16
+ PortTo uint16
HashSize uint32
NumEntries uint32
@@ -52,6 +66,12 @@ type IpsetCreateOptions struct {
Counters bool
Comments bool
Skbinfo bool
+
+ Revision uint8
+ IPFrom net.IP
+ IPTo net.IP
+ PortFrom uint16
+ PortTo uint16
}
// IpsetProtocol returns the ipset protocol version from the kernel
@@ -86,12 +106,12 @@ func IpsetListAll() ([]IPSetResult, error) {
// IpsetAdd adds an entry to an existing ipset.
func IpsetAdd(setname string, entry *IPSetEntry) error {
- return pkgHandle.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
+ return pkgHandle.IpsetAdd(setname, entry)
}
// IpsetDel deletes an entry from an existing ipset.
func IpsetDel(setname string, entry *IPSetEntry) error {
- return pkgHandle.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
+ return pkgHandle.IpsetDel(setname, entry)
}
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
@@ -114,11 +134,30 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
- req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(0)))
- req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(2))) // 2 == inet
+
+ revision := options.Revision
+ if revision == 0 {
+ revision = getIpsetDefaultWithTypeName(typename)
+ }
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(revision)))
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
+ var family uint8
+ switch typename {
+ case "hash:mac":
+ case "bitmap:port":
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint16(buf, options.PortFrom)
+ binary.BigEndian.PutUint16(buf[2:], options.PortTo)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2]))
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:]))
+ default:
+ family = unix.AF_INET
+ }
+
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family)))
+
if timeout := options.Timeout; timeout != nil {
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
}
@@ -187,6 +226,16 @@ func (h *Handle) IpsetListAll() ([]IPSetResult, error) {
return result, nil
}
+// IpsetAdd adds an entry to an existing ipset.
+func (h *Handle) IpsetAdd(setname string, entry *IPSetEntry) error {
+ return h.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
+}
+
+// IpsetDel deletes an entry from an existing ipset.
+func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error {
+ return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
+}
+
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
req := h.newIpsetRequest(nlCmd)
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
@@ -204,15 +253,49 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
if entry.Timeout != nil {
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
}
- if entry.MAC != nil {
- nestedData := nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NET_BYTEORDER), entry.MAC)
- data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NESTED), nestedData.Serialize()))
- }
+
if entry.IP != nil {
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
}
+ if entry.MAC != nil {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER, entry.MAC))
+ }
+
+ if entry.CIDR != 0 {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR, nl.Uint8Attr(entry.CIDR)))
+ }
+
+ if entry.IP2 != nil {
+ nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize()))
+ }
+
+ if entry.CIDR2 != 0 {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR2, nl.Uint8Attr(entry.CIDR2)))
+ }
+
+ if entry.Port != nil {
+ if entry.Protocol == nil {
+ // use tcp protocol as default
+ val := uint8(unix.IPPROTO_TCP)
+ entry.Protocol = &val
+ }
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PROTO, nl.Uint8Attr(*entry.Protocol)))
+ buf := make([]byte, 2)
+ binary.BigEndian.PutUint16(buf, *entry.Port)
+ data.AddChild(nl.NewRtAttr(int(nl.IPSET_ATTR_PORT|nl.NLA_F_NET_BYTEORDER), buf))
+ }
+
+ if entry.IFace != "" {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IFACE, nl.ZeroTerminated(entry.IFace)))
+ }
+
+ if entry.Mark != nil {
+ data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER, Value: *entry.Mark})
+ }
+
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
req.AddData(data)
@@ -235,6 +318,17 @@ func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
return req
}
+func getIpsetDefaultWithTypeName(typename string) uint8 {
+ switch typename {
+ case "hash:ip,port",
+ "hash:ip,port,ip",
+ "hash:ip,port,net",
+ "hash:net,port":
+ return 1
+ }
+ return 0
+}
+
func ipsetExecute(req *nl.NetlinkRequest) (msgs [][]byte, err error) {
msgs, err = req.Execute(unix.NETLINK_NETFILTER, 0)
@@ -278,6 +372,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.parseAttrADT(attr.Value)
case nl.IPSET_ATTR_PROTOCOL_MIN:
result.ProtocolMinVersion = attr.Value[0]
+ case nl.IPSET_ATTR_MARKMASK:
+ result.MarkMask = attr.Uint32()
default:
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -307,12 +403,31 @@ func (result *IPSetResult) parseAttrData(data []byte) {
switch nested.Type {
case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER:
result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value})
+ case nl.IPSET_ATTR_IP:
+ result.IPFrom = nested.Value
+ default:
+ log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
+ }
+ }
+ case nl.IPSET_ATTR_IP_TO | nl.NLA_F_NESTED:
+ for nested := range nl.ParseAttributes(attr.Value) {
+ switch nested.Type {
+ case nl.IPSET_ATTR_IP:
+ result.IPTo = nested.Value
+ default:
+ log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
}
}
+ case nl.IPSET_ATTR_PORT_FROM | nl.NLA_F_NET_BYTEORDER:
+ result.PortFrom = networkOrder.Uint16(attr.Value)
+ case nl.IPSET_ATTR_PORT_TO | nl.NLA_F_NET_BYTEORDER:
+ result.PortTo = networkOrder.Uint16(attr.Value)
case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
result.LineNo = attr.Uint32()
case nl.IPSET_ATTR_COMMENT:
result.Comment = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_MARKMASK:
+ result.MarkMask = attr.Uint32()
default:
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -357,6 +472,30 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
}
}
+ case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED:
+ for attr := range nl.ParseAttributes(attr.Value) {
+ switch attr.Type {
+ case nl.IPSET_ATTR_IP:
+ entry.IP2 = net.IP(attr.Value)
+ default:
+ log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
+ }
+ }
+ case nl.IPSET_ATTR_CIDR:
+ entry.CIDR = attr.Value[0]
+ case nl.IPSET_ATTR_CIDR2:
+ entry.CIDR2 = attr.Value[0]
+ case nl.IPSET_ATTR_PORT | nl.NLA_F_NET_BYTEORDER:
+ val := networkOrder.Uint16(attr.Value)
+ entry.Port = &val
+ case nl.IPSET_ATTR_PROTO:
+ val := attr.Value[0]
+ entry.Protocol = &val
+ case nl.IPSET_ATTR_IFACE:
+ entry.IFace = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER:
+ val := attr.Uint32()
+ entry.Mark = &val
default:
log.Printf("unknown ADT attribute from kernel: %+v", attr)
}
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index 32ca7cd64..82d0360eb 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -35,10 +35,13 @@ type LinkAttrs struct {
Alias string
Statistics *LinkStatistics
Promisc int
+ Allmulti int
+ Multi int
Xdp *LinkXdp
EncapType string
Protinfo *Protinfo
OperState LinkOperState
+ PhysSwitchID int
NetNsID int
NumTxQueues int
NumRxQueues int
@@ -456,6 +459,19 @@ func (ipvlan *IPVlan) Type() string {
return "ipvlan"
}
+// IPVtap - IPVtap is a virtual interfaces based on ipvlan
+type IPVtap struct {
+ IPVlan
+}
+
+func (ipvtap *IPVtap) Attrs() *LinkAttrs {
+ return &ipvtap.LinkAttrs
+}
+
+func (ipvtap IPVtap) Type() string {
+ return "ipvtap"
+}
+
// VlanProtocol type
type VlanProtocol int
@@ -946,6 +962,14 @@ func (b *BondSlave) SlaveType() string {
return "bond"
}
+type VrfSlave struct {
+ Table uint32
+}
+
+func (v *VrfSlave) SlaveType() string {
+ return "vrf"
+}
+
// Geneve devices must specify RemoteIP and ID (VNI) on create
// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
type Geneve struct {
@@ -1049,6 +1073,37 @@ func (ip6tnl *Ip6tnl) Type() string {
return "ip6tnl"
}
+// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L84
+type TunnelEncapType uint16
+
+const (
+ None TunnelEncapType = iota
+ FOU
+ GUE
+)
+
+// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L91
+type TunnelEncapFlag uint16
+
+const (
+ CSum TunnelEncapFlag = 1 << 0
+ CSum6 = 1 << 1
+ RemCSum = 1 << 2
+)
+
+// from https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip6_tunnel.h#L12
+type IP6TunnelFlag uint16
+
+const (
+ IP6_TNL_F_IGN_ENCAP_LIMIT IP6TunnelFlag = 1 // don't add encapsulation limit if one isn't present in inner packet
+ IP6_TNL_F_USE_ORIG_TCLASS = 2 // copy the traffic class field from the inner packet
+ IP6_TNL_F_USE_ORIG_FLOWLABEL = 4 // copy the flowlabel from the inner packet
+ IP6_TNL_F_MIP6_DEV = 8 // being used for Mobile IPv6
+ IP6_TNL_F_RCV_DSCP_COPY = 10 // copy DSCP from the outer packet
+ IP6_TNL_F_USE_ORIG_FWMARK = 20 // copy fwmark from inner packet
+ IP6_TNL_F_ALLOW_LOCAL_REMOTE = 40 // allow remote endpoint on the local node
+)
+
type Sittun struct {
LinkAttrs
Link uint32
@@ -1260,11 +1315,27 @@ func (ipoib *IPoIB) Type() string {
return "ipoib"
}
+type BareUDP struct {
+ LinkAttrs
+ Port uint16
+ EtherType uint16
+ SrcPortMin uint16
+ MultiProto bool
+}
+
+func (bareudp *BareUDP) Attrs() *LinkAttrs {
+ return &bareudp.LinkAttrs
+}
+
+func (bareudp *BareUDP) Type() string {
+ return "bareudp"
+}
+
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
-// bond_slave | ipvlan | xfrm
+// bond_slave | ipvlan | xfrm | bareudp
// LinkNotFoundError wraps the various not found errors when
// getting/reading links. This is intended for better error
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index 3b959299c..aa998e311 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -55,8 +55,6 @@ const (
VF_LINK_STATE_DISABLE uint32 = 2
)
-var lookupByDump = false
-
var macvlanModes = [...]uint32{
0,
nl.MACVLAN_MODE_PRIVATE,
@@ -153,7 +151,6 @@ func (h *Handle) LinkSetAllmulticastOn(link Link) error {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Change = unix.IFF_ALLMULTI
msg.Flags = unix.IFF_ALLMULTI
-
msg.Index = int32(base.Index)
req.AddData(msg)
@@ -183,6 +180,51 @@ func (h *Handle) LinkSetAllmulticastOff(link Link) error {
return err
}
+// LinkSetMulticastOn enables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast on`
+func LinkSetMulticastOn(link Link) error {
+ return pkgHandle.LinkSetMulticastOn(link)
+}
+
+// LinkSetMulticastOn enables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast on`
+func (h *Handle) LinkSetMulticastOn(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_MULTICAST
+ msg.Flags = unix.IFF_MULTICAST
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast off`
+func LinkSetMulticastOff(link Link) error {
+ return pkgHandle.LinkSetMulticastOff(link)
+}
+
+// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast off`
+func (h *Handle) LinkSetMulticastOff(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_MULTICAST
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
return pkgHandle.MacvlanMACAddrAdd(link, addr)
}
@@ -547,13 +589,13 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfVlan{
Vf: uint32(vf),
Vlan: uint32(vlan),
Qos: uint32(qos),
}
- nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
@@ -1104,6 +1146,10 @@ func (h *Handle) LinkAdd(link Link) error {
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
}
+func LinkModify(link Link) error {
+ return pkgHandle.LinkModify(link)
+}
+
func (h *Handle) LinkModify(link Link) error {
return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
}
@@ -1218,9 +1264,26 @@ func (h *Handle) linkModify(link Link, flags int) error {
}
+ control := func(file *os.File, f func(fd uintptr)) error {
+ name := file.Name()
+ conn, err := file.SyscallConn()
+ if err != nil {
+ return fmt.Errorf("SyscallConn() failed on %s: %v", name, err)
+ }
+ if err := conn.Control(f); err != nil {
+ return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err)
+ }
+ return nil
+ }
+
// only persist interface if NonPersist is NOT set
if !tuntap.NonPersist {
- _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1)
+ var errno syscall.Errno
+ if err := control(fds[0], func(fd uintptr) {
+ _, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1)
+ }); err != nil {
+ return err
+ }
if errno != 0 {
cleanupFds(fds)
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
@@ -1237,7 +1300,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
// un-persist (e.g. allow the interface to be removed) the tuntap
// should not hurt if not set prior, condition might be not needed
if !tuntap.NonPersist {
- _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0)
+ // ignore error
+ _ = control(fds[0], func(fd uintptr) {
+ _, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0)
+ })
}
cleanupFds(fds)
return err
@@ -1409,6 +1475,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
+ case *IPVtap:
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
+ data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
case *Macvlan:
if link.Mode != MACVLAN_MODE_DEFAULT {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@@ -1443,6 +1513,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
addXfrmiAttrs(link, linkInfo)
case *IPoIB:
addIPoIBAttrs(link, linkInfo)
+ case *BareUDP:
+ addBareUDPAttrs(link, linkInfo)
}
req.AddData(linkInfo)
@@ -1624,7 +1696,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
}
}
-// linkDeserialize deserializes a raw message received from netlink into
+// LinkDeserialize deserializes a raw message received from netlink into
// a link object.
func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
msg := nl.DeserializeIfInfomsg(m)
@@ -1639,9 +1711,17 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.RawFlags = msg.Flags
base.Flags = linkFlags(msg.Flags)
base.EncapType = msg.EncapType()
+ base.NetNsID = -1
if msg.Flags&unix.IFF_PROMISC != 0 {
base.Promisc = 1
}
+ if msg.Flags&unix.IFF_ALLMULTI != 0 {
+ base.Allmulti = 1
+ }
+ if msg.Flags&unix.IFF_MULTICAST != 0 {
+ base.Multi = 1
+ }
+
var (
link Link
stats32 *LinkStatistics32
@@ -1680,6 +1760,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Bond{}
case "ipvlan":
link = &IPVlan{}
+ case "ipvtap":
+ link = &IPVtap{}
case "macvlan":
link = &Macvlan{}
case "macvtap":
@@ -1714,6 +1796,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &IPoIB{}
case "can":
link = &Can{}
+ case "bareudp":
+ link = &BareUDP{}
default:
link = &GenericLink{LinkType: linkType}
}
@@ -1731,6 +1815,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseBondData(link, data)
case "ipvlan":
parseIPVlanData(link, data)
+ case "ipvtap":
+ parseIPVtapData(link, data)
case "macvlan":
parseMacvlanData(link, data)
case "macvtap":
@@ -1767,13 +1853,19 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseIPoIBData(link, data)
case "can":
parseCanData(link, data)
+ case "bareudp":
+ parseBareUDPData(link, data)
}
+
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
switch slaveType {
case "bond":
linkSlave = &BondSlave{}
+ case "vrf":
+ linkSlave = &VrfSlave{}
}
+
case nl.IFLA_INFO_SLAVE_DATA:
switch slaveType {
case "bond":
@@ -1782,6 +1874,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
return nil, err
}
parseBondSlaveData(linkSlave, data)
+ case "vrf":
+ data, err := nl.ParseRouteAttr(info.Value)
+ if err != nil {
+ return nil, err
+ }
+ parseVrfSlaveData(linkSlave, data)
}
}
}
@@ -1835,6 +1933,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
}
case unix.IFLA_OPERSTATE:
base.OperState = LinkOperState(uint8(attr.Value[0]))
+ case unix.IFLA_PHYS_SWITCH_ID:
+ base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_LINK_NETNSID:
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_GSO_MAX_SIZE:
@@ -2023,7 +2123,8 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -2038,15 +2139,15 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
ifmsg := nl.DeserializeIfInfomsg(m.Data)
header := unix.NlMsghdr(m.Header)
@@ -2055,7 +2156,7 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
if cberr != nil {
cberr(err)
}
- return
+ continue
}
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
}
@@ -2404,6 +2505,16 @@ func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
}
}
+func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
+ vrfSlave := slave.(*VrfSlave)
+ for i := range data {
+ switch data[i].Attr.Type {
+ case nl.IFLA_BOND_SLAVE_STATE:
+ vrfSlave.Table = native.Uint32(data[i].Value[0:4])
+ }
+ }
+}
+
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan)
for _, datum := range data {
@@ -2416,6 +2527,18 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
+ ipv := link.(*IPVtap)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_IPVLAN_MODE:
+ ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
+ case nl.IFLA_IPVLAN_FLAG:
+ ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
+ }
+ }
+}
+
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
macv := link.(*Macvtap)
parseMacvlanData(&macv.Macvlan, data)
@@ -2756,6 +2879,10 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
iptun := link.(*Iptun)
for _, datum := range data {
+ // NOTE: same with vxlan, ip tunnel may also has null datum.Value
+ if len(datum.Value) == 0 {
+ continue
+ }
switch datum.Attr.Type {
case nl.IFLA_IPTUN_LOCAL:
iptun.Local = net.IP(datum.Value[0:4])
@@ -3303,3 +3430,32 @@ func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
}
+
+func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port)))
+ data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType)))
+ if bareudp.SrcPortMin != 0 {
+ data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin))
+ }
+ if bareudp.MultiProto {
+ data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{})
+ }
+}
+
+func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) {
+ bareudp := link.(*BareUDP)
+ for _, attr := range data {
+ switch attr.Attr.Type {
+ case nl.IFLA_BAREUDP_PORT:
+ bareudp.Port = binary.BigEndian.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_ETHERTYPE:
+ bareudp.EtherType = binary.BigEndian.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_SRCPORT_MIN:
+ bareudp.SrcPortMin = native.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_MULTIPROTO_MODE:
+ bareudp.MultiProto = true
+ }
+ }
+}
diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go
index 379e5655f..32d722e88 100644
--- a/vendor/github.com/vishvananda/netlink/neigh.go
+++ b/vendor/github.com/vishvananda/netlink/neigh.go
@@ -12,6 +12,7 @@ type Neigh struct {
State int
Type int
Flags int
+ FlagsExt int
IP net.IP
HardwareAddr net.HardwareAddr
LLIPAddr net.IP //Used in the case of NHRP
diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go
index fb220d141..4c1e76635 100644
--- a/vendor/github.com/vishvananda/netlink/neigh_linux.go
+++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go
@@ -24,7 +24,11 @@ const (
NDA_MASTER
NDA_LINK_NETNSID
NDA_SRC_VNI
- NDA_MAX = NDA_SRC_VNI
+ NDA_PROTOCOL
+ NDA_NH_ID
+ NDA_FDB_EXT_ATTRS
+ NDA_FLAGS_EXT
+ NDA_MAX = NDA_FLAGS_EXT
)
// Neighbor Cache Entry States.
@@ -42,11 +46,19 @@ const (
// Neighbor Flags
const (
- NTF_USE = 0x01
- NTF_SELF = 0x02
- NTF_MASTER = 0x04
- NTF_PROXY = 0x08
- NTF_ROUTER = 0x80
+ NTF_USE = 0x01
+ NTF_SELF = 0x02
+ NTF_MASTER = 0x04
+ NTF_PROXY = 0x08
+ NTF_EXT_LEARNED = 0x10
+ NTF_OFFLOADED = 0x20
+ NTF_STICKY = 0x40
+ NTF_ROUTER = 0x80
+)
+
+// Extended Neighbor Flags
+const (
+ NTF_EXT_MANAGED = 0x00000001
)
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
@@ -162,11 +174,16 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
if neigh.LLIPAddr != nil {
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
req.AddData(llIPData)
- } else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
+ } else if neigh.HardwareAddr != nil {
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
}
+ if neigh.FlagsExt != 0 {
+ flagsExtData := nl.NewRtAttr(NDA_FLAGS_EXT, nl.Uint32Attr(uint32(neigh.FlagsExt)))
+ req.AddData(flagsExtData)
+ }
+
if neigh.Vlan != 0 {
vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
req.AddData(vlanData)
@@ -305,6 +322,8 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
} else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
+ case NDA_FLAGS_EXT:
+ neigh.FlagsExt = int(native.Uint32(attr.Value[0:4]))
case NDA_VLAN:
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
case NDA_VNI:
@@ -408,7 +427,6 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
index 71436f25c..98d2c0dbf 100644
--- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
@@ -180,14 +180,30 @@ func RouteAdd(route *Route) error {
return ErrNotImplemented
}
+func RouteAppend(route *Route) error {
+ return ErrNotImplemented
+}
+
func RouteDel(route *Route) error {
return ErrNotImplemented
}
+func RouteGet(destination net.IP) ([]Route, error) {
+ return nil, ErrNotImplemented
+}
+
func RouteList(link Link, family int) ([]Route, error) {
return nil, ErrNotImplemented
}
+func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
+ return nil, ErrNotImplemented
+}
+
+func RouteReplace(route *Route) error {
+ return ErrNotImplemented
+}
+
func XfrmPolicyAdd(policy *XfrmPolicy) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go
index 77cf6f469..2eb29c7ce 100644
--- a/vendor/github.com/vishvananda/netlink/netns_linux.go
+++ b/vendor/github.com/vishvananda/netlink/netns_linux.go
@@ -87,7 +87,7 @@ func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
- b := make([]byte, 4, 4)
+ b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
@@ -126,12 +126,12 @@ func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
- b := make([]byte, 4, 4)
+ b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
- b1 := make([]byte, 4, 4)
+ b1 := make([]byte, 4)
native.PutUint32(b1, newnsid)
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
req.AddData(attr1)
diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
index 14924027e..183601803 100644
--- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
@@ -44,6 +44,7 @@ const (
NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15)
NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14)
NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
+ NLA_ALIGNTO uint16 = 4 // #define NLA_ALIGNTO 4
)
// enum ctattr_type {
diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
index aa6155e21..2995da492 100644
--- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
@@ -11,22 +11,37 @@ const (
const (
DEVLINK_CMD_GET = 1
DEVLINK_CMD_PORT_GET = 5
+ DEVLINK_CMD_PORT_SET = 6
+ DEVLINK_CMD_PORT_NEW = 7
+ DEVLINK_CMD_PORT_DEL = 8
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
+ DEVLINK_CMD_INFO_GET = 51
)
const (
- DEVLINK_ATTR_BUS_NAME = 1
- DEVLINK_ATTR_DEV_NAME = 2
- DEVLINK_ATTR_PORT_INDEX = 3
- DEVLINK_ATTR_PORT_TYPE = 4
- DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
- DEVLINK_ATTR_PORT_NETDEV_NAME = 7
- DEVLINK_ATTR_PORT_IBDEV_NAME = 8
- DEVLINK_ATTR_ESWITCH_MODE = 25
- DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
- DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
- DEVLINK_ATTR_PORT_FLAVOUR = 77
+ DEVLINK_ATTR_BUS_NAME = 1
+ DEVLINK_ATTR_DEV_NAME = 2
+ DEVLINK_ATTR_PORT_INDEX = 3
+ DEVLINK_ATTR_PORT_TYPE = 4
+ DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
+ DEVLINK_ATTR_PORT_NETDEV_NAME = 7
+ DEVLINK_ATTR_PORT_IBDEV_NAME = 8
+ DEVLINK_ATTR_ESWITCH_MODE = 25
+ DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
+ DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
+ DEVLINK_ATTR_PORT_FLAVOUR = 77
+ DEVLINK_ATTR_INFO_DRIVER_NAME = 98
+ DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
+ DEVLINK_ATTR_INFO_VERSION_FIXED = 100
+ DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
+ DEVLINK_ATTR_INFO_VERSION_STORED = 102
+ DEVLINK_ATTR_INFO_VERSION_NAME = 103
+ DEVLINK_ATTR_INFO_VERSION_VALUE = 104
+ DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
+ DEVLINK_ATTR_PORT_FUNCTION = 145
+ DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
+ DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
)
const (
@@ -53,6 +68,8 @@ const (
DEVLINK_PORT_FLAVOUR_PCI_PF = 3
DEVLINK_PORT_FLAVOUR_PCI_VF = 4
DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
+ DEVLINK_PORT_FLAVOUR_UNUSED = 6
+ DEVLINK_PORT_FLAVOUR_PCI_SF = 7
)
const (
@@ -61,3 +78,19 @@ const (
DEVLINK_PORT_TYPE_ETH = 2
DEVLINK_PORT_TYPE_IB = 3
)
+
+const (
+ DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR = 1
+ DEVLINK_PORT_FN_ATTR_STATE = 2
+ DEVLINK_PORT_FN_ATTR_OPSTATE = 3
+)
+
+const (
+ DEVLINK_PORT_FN_STATE_INACTIVE = 0
+ DEVLINK_PORT_FN_STATE_ACTIVE = 1
+)
+
+const (
+ DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
+ DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index c72cc436e..e10edbc09 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -709,3 +709,12 @@ const (
IFLA_CAN_BITRATE_MAX
IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
)
+
+const (
+ IFLA_BAREUDP_UNSPEC = iota
+ IFLA_BAREUDP_PORT
+ IFLA_BAREUDP_ETHERTYPE
+ IFLA_BAREUDP_SRCPORT_MIN
+ IFLA_BAREUDP_MULTIPROTO_MODE
+ IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
new file mode 100644
index 000000000..bafd593c4
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
@@ -0,0 +1,29 @@
+package nl
+
+const (
+ LWT_BPF_PROG_UNSPEC = iota
+ LWT_BPF_PROG_FD
+ LWT_BPF_PROG_NAME
+ __LWT_BPF_PROG_MAX
+)
+
+const (
+ LWT_BPF_PROG_MAX = __LWT_BPF_PROG_MAX - 1
+)
+
+const (
+ LWT_BPF_UNSPEC = iota
+ LWT_BPF_IN
+ LWT_BPF_OUT
+ LWT_BPF_XMIT
+ LWT_BPF_XMIT_HEADROOM
+ __LWT_BPF_MAX
+)
+
+const (
+ LWT_BPF_MAX = __LWT_BPF_MAX - 1
+)
+
+const (
+ LWT_BPF_MAX_HEADROOM = 256
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index dcd4b9469..a49f67570 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -27,7 +27,8 @@ const (
// tc rules or filters, or other more memory requiring data.
RECEIVE_BUFFER_SIZE = 65536
// Kernel netlink pid
- PidKernel uint32 = 0
+ PidKernel uint32 = 0
+ SizeofCnMsgOp = 0x18
)
// SupportedNlFamilies contains the list of netlink families this netlink package supports
@@ -85,6 +86,56 @@ type NetlinkRequestData interface {
Serialize() []byte
}
+const (
+ PROC_CN_MCAST_LISTEN = 1
+ PROC_CN_MCAST_IGNORE
+)
+
+type CbID struct {
+ Idx uint32
+ Val uint32
+}
+
+type CnMsg struct {
+ ID CbID
+ Seq uint32
+ Ack uint32
+ Length uint16
+ Flags uint16
+}
+
+type CnMsgOp struct {
+ CnMsg
+ // here we differ from the C header
+ Op uint32
+}
+
+func NewCnMsg(idx, val, op uint32) *CnMsgOp {
+ var cm CnMsgOp
+
+ cm.ID.Idx = idx
+ cm.ID.Val = val
+
+ cm.Ack = 0
+ cm.Seq = 1
+ cm.Length = uint16(binary.Size(op))
+ cm.Op = op
+
+ return &cm
+}
+
+func (msg *CnMsgOp) Serialize() []byte {
+ return (*(*[SizeofCnMsgOp]byte)(unsafe.Pointer(msg)))[:]
+}
+
+func DeserializeCnMsgOp(b []byte) *CnMsgOp {
+ return (*CnMsgOp)(unsafe.Pointer(&b[0:SizeofCnMsgOp][0]))
+}
+
+func (msg *CnMsgOp) Len() int {
+ return SizeofCnMsgOp
+}
+
// IfInfomsg is related to links, but it is used for list requests as well
type IfInfomsg struct {
unix.IfInfomsg
diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
index 1224b747d..ce43ee155 100644
--- a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
@@ -11,6 +11,8 @@ const (
const (
RDMA_NLDEV_CMD_GET = 1
RDMA_NLDEV_CMD_SET = 2
+ RDMA_NLDEV_CMD_NEWLINK = 3
+ RDMA_NLDEV_CMD_DELLINK = 4
RDMA_NLDEV_CMD_SYS_GET = 6
RDMA_NLDEV_CMD_SYS_SET = 7
)
@@ -30,6 +32,8 @@ const (
RDMA_NLDEV_ATTR_PORT_STATE = 12
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
+ RDMA_NLDEV_ATTR_NDEV_NAME = 51
+ RDMA_NLDEV_ATTR_LINK_TYPE = 65
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
RDMA_NLDEV_NET_NS_FD = 68
)
diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
index 5774cbb15..fe88285f2 100644
--- a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
@@ -23,7 +23,7 @@ func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool {
return false
}
for i := range s1.Segments {
- if s1.Segments[i].Equal(s2.Segments[i]) != true {
+ if !s1.Segments[i].Equal(s2.Segments[i]) {
return false
}
}
@@ -89,7 +89,7 @@ func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
}
buf = buf[12:]
if len(buf)%16 != 0 {
- err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf))
+ err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)", len(buf))
return mode, nil, err
}
for len(buf) > 0 {
diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go
index 4a01e6e59..bdf6ba639 100644
--- a/vendor/github.com/vishvananda/netlink/nl/syscall.go
+++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go
@@ -1,6 +1,6 @@
package nl
-// syscall package lack of rule atributes type.
+// syscall package lack of rule attributes type.
// Thus there are defined below
const (
FRA_UNSPEC = iota
diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
index c24d53eb7..002beda92 100644
--- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
@@ -882,6 +882,111 @@ const (
TCA_HFSC_USC
)
+const (
+ TCA_FLOWER_UNSPEC = iota
+ TCA_FLOWER_CLASSID
+ TCA_FLOWER_INDEV
+ TCA_FLOWER_ACT
+ TCA_FLOWER_KEY_ETH_DST /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_DST_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_TYPE /* be16 */
+ TCA_FLOWER_KEY_IP_PROTO /* u8 */
+ TCA_FLOWER_KEY_IPV4_SRC /* be32 */
+ TCA_FLOWER_KEY_IPV4_SRC_MASK /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST_MASK /* be32 */
+ TCA_FLOWER_KEY_IPV6_SRC /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_SRC_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_TCP_SRC /* be16 */
+ TCA_FLOWER_KEY_TCP_DST /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC /* be16 */
+ TCA_FLOWER_KEY_UDP_DST /* be16 */
+
+ TCA_FLOWER_FLAGS
+ TCA_FLOWER_KEY_VLAN_ID /* be16 */
+ TCA_FLOWER_KEY_VLAN_PRIO /* u8 */
+ TCA_FLOWER_KEY_VLAN_ETH_TYPE /* be16 */
+
+ TCA_FLOWER_KEY_ENC_KEY_ID /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST_MASK /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST_MASK /* struct in6_addr */
+
+ TCA_FLOWER_KEY_TCP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_TCP_DST_MASK /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_UDP_DST_MASK /* be16 */
+ TCA_FLOWER_KEY_SCTP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST_MASK /* be16 */
+
+ TCA_FLOWER_KEY_SCTP_SRC /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST /* be16 */
+
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK /* be16 */
+
+ TCA_FLOWER_KEY_FLAGS /* be32 */
+ TCA_FLOWER_KEY_FLAGS_MASK /* be32 */
+
+ TCA_FLOWER_KEY_ICMPV4_CODE /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK /* u8 */
+
+ TCA_FLOWER_KEY_ARP_SIP /* be32 */
+ TCA_FLOWER_KEY_ARP_SIP_MASK /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP_MASK /* be32 */
+ TCA_FLOWER_KEY_ARP_OP /* u8 */
+ TCA_FLOWER_KEY_ARP_OP_MASK /* u8 */
+ TCA_FLOWER_KEY_ARP_SHA /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_SHA_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA_MASK /* ETH_ALEN */
+
+ TCA_FLOWER_KEY_MPLS_TTL /* u8 - 8 bits */
+ TCA_FLOWER_KEY_MPLS_BOS /* u8 - 1 bit */
+ TCA_FLOWER_KEY_MPLS_TC /* u8 - 3 bits */
+ TCA_FLOWER_KEY_MPLS_LABEL /* be32 - 20 bits */
+
+ TCA_FLOWER_KEY_TCP_FLAGS /* be16 */
+ TCA_FLOWER_KEY_TCP_FLAGS_MASK /* be16 */
+
+ TCA_FLOWER_KEY_IP_TOS /* u8 */
+ TCA_FLOWER_KEY_IP_TOS_MASK /* u8 */
+ TCA_FLOWER_KEY_IP_TTL /* u8 */
+ TCA_FLOWER_KEY_IP_TTL_MASK /* u8 */
+
+ TCA_FLOWER_KEY_CVLAN_ID /* be16 */
+ TCA_FLOWER_KEY_CVLAN_PRIO /* u8 */
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE /* be16 */
+
+ TCA_FLOWER_KEY_ENC_IP_TOS /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TOS_MASK /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL_MASK /* u8 */
+
+ TCA_FLOWER_KEY_ENC_OPTS
+ TCA_FLOWER_KEY_ENC_OPTS_MASK
+
+ __TCA_FLOWER_MAX
+)
+
// struct tc_sfq_qopt {
// unsigned quantum; /* Bytes per round allocated to flow */
// int perturb_period; /* Period of hash perturbation */
diff --git a/vendor/github.com/vishvananda/netlink/proc_event.go b/vendor/github.com/vishvananda/netlink/proc_event.go
new file mode 100644
index 000000000..53bc59a6e
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/proc_event.go
@@ -0,0 +1,217 @@
+package netlink
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "os"
+ "syscall"
+
+ "github.com/vishvananda/netlink/nl"
+ "github.com/vishvananda/netns"
+ "golang.org/x/sys/unix"
+)
+
+const CN_IDX_PROC = 0x1
+
+const (
+ PROC_EVENT_NONE = 0x00000000
+ PROC_EVENT_FORK = 0x00000001
+ PROC_EVENT_EXEC = 0x00000002
+ PROC_EVENT_UID = 0x00000004
+ PROC_EVENT_GID = 0x00000040
+ PROC_EVENT_SID = 0x00000080
+ PROC_EVENT_PTRACE = 0x00000100
+ PROC_EVENT_COMM = 0x00000200
+ PROC_EVENT_COREDUMP = 0x40000000
+ PROC_EVENT_EXIT = 0x80000000
+)
+
+const (
+ CN_VAL_PROC = 0x1
+ PROC_CN_MCAST_LISTEN = 0x1
+)
+
+type ProcEventMsg interface {
+ Pid() uint32
+ Tgid() uint32
+}
+
+type ProcEventHeader struct {
+ What uint32
+ CPU uint32
+ Timestamp uint64
+}
+
+type ProcEvent struct {
+ ProcEventHeader
+ Msg ProcEventMsg
+}
+
+func (pe *ProcEvent) setHeader(h ProcEventHeader) {
+ pe.What = h.What
+ pe.CPU = h.CPU
+ pe.Timestamp = h.Timestamp
+}
+
+type ExitProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ ExitCode uint32
+ ExitSignal uint32
+ ParentPid uint32
+ ParentTgid uint32
+}
+
+type ExitProcEvent2 struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ ExitCode uint32
+ ExitSignal uint32
+ ParentPid uint32
+ ParentTgid uint32
+}
+
+func (e *ExitProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *ExitProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+type ExecProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+}
+
+func (e *ExecProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *ExecProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+type ForkProcEvent struct {
+ ParentPid uint32
+ ParentTgid uint32
+ ChildPid uint32
+ ChildTgid uint32
+}
+
+func (e *ForkProcEvent) Pid() uint32 {
+ return e.ParentPid
+}
+
+func (e *ForkProcEvent) Tgid() uint32 {
+ return e.ParentTgid
+}
+
+type CommProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ Comm [16]byte
+}
+
+func (e *CommProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *CommProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
+ h, err := NewHandle()
+ if err != nil {
+ return err
+ }
+ defer h.Delete()
+
+ s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
+ if err != nil {
+ return err
+ }
+
+ var nlmsg nl.NetlinkRequest
+
+ nlmsg.Pid = uint32(os.Getpid())
+ nlmsg.Type = unix.NLMSG_DONE
+ nlmsg.Len = uint32(unix.SizeofNlMsghdr)
+
+ cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
+ nlmsg.AddData(cm)
+
+ s.Send(&nlmsg)
+
+ if done != nil {
+ go func() {
+ <-done
+ s.Close()
+ }()
+ }
+
+ go func() {
+ defer close(ch)
+ for {
+ msgs, from, err := s.Receive()
+ if err != nil {
+ errorChan <- err
+ return
+ }
+ if from.Pid != nl.PidKernel {
+ errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ return
+ }
+
+ for _, m := range msgs {
+ e := parseNetlinkMessage(m)
+ if e != nil {
+ ch <- *e
+ }
+ }
+
+ }
+ }()
+
+ return nil
+}
+
+func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
+ if m.Header.Type == unix.NLMSG_DONE {
+ buf := bytes.NewBuffer(m.Data)
+ msg := &nl.CnMsg{}
+ hdr := &ProcEventHeader{}
+ binary.Read(buf, nl.NativeEndian(), msg)
+ binary.Read(buf, nl.NativeEndian(), hdr)
+
+ pe := &ProcEvent{}
+ pe.setHeader(*hdr)
+ switch hdr.What {
+ case PROC_EVENT_EXIT:
+ event := &ExitProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_FORK:
+ event := &ForkProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_EXEC:
+ event := &ExecProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_COMM:
+ event := &CommProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ }
+ return nil
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index edc4b726a..e182e1cfe 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -468,7 +468,6 @@ func parsePrioData(qdisc Qdisc, value []byte) error {
}
func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
htb := qdisc.(*Htb)
for _, datum := range data {
switch datum.Attr.Type {
@@ -488,7 +487,6 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
}
func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
fqCodel := qdisc.(*FqCodel)
for _, datum := range data {
@@ -518,13 +516,11 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
func parseHfscData(qdisc Qdisc, data []byte) error {
Hfsc := qdisc.(*Hfsc)
- native = nl.NativeEndian()
Hfsc.Defcls = native.Uint16(data)
return nil
}
func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
fq := qdisc.(*Fq)
for _, datum := range data {
switch datum.Attr.Type {
@@ -589,7 +585,6 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
}
func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
tbf := qdisc.(*Tbf)
for _, datum := range data {
switch datum.Attr.Type {
@@ -711,3 +706,7 @@ func Xmittime(rate uint64, size uint32) uint32 {
// https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62
return time2Tick(uint32(TIME_UNITS_PER_SEC * (float64(size) / float64(rate))))
}
+
+func Xmitsize(rate uint64, ticks uint32) uint32 {
+ return uint32((float64(rate) * float64(tick2Time(ticks))) / TIME_UNITS_PER_SEC)
+}
diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
index ff014ca4c..036399db6 100644
--- a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
@@ -278,3 +278,54 @@ func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
return execRdmaSetLink(req)
}
+
+// RdmaLinkDel deletes an rdma link
+//
+// Similar to: rdma link delete NAME
+// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html
+func RdmaLinkDel(name string) error {
+ return pkgHandle.RdmaLinkDel(name)
+}
+
+// RdmaLinkDel deletes an rdma link.
+func (h *Handle) RdmaLinkDel(name string) error {
+ link, err := h.RdmaLinkByName(name)
+ if err != nil {
+ return err
+ }
+
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_DELLINK)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ b := make([]byte, 4)
+ native.PutUint32(b, link.Attrs.Index)
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b))
+
+ _, err = req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
+
+// RdmaLinkAdd adds an rdma link for the specified type to the network device.
+// Similar to: rdma link add NAME type TYPE netdev NETDEV
+// NAME - specifies the new name of the rdma link to add
+// TYPE - specifies which rdma type to use. Link types:
+// rxe - Soft RoCE driver
+// siw - Soft iWARP driver
+// NETDEV - specifies the network device to which the link is bound
+//
+// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html
+func RdmaLinkAdd(linkName, linkType, netdev string) error {
+ return pkgHandle.RdmaLinkAdd(linkName, linkType, netdev)
+}
+
+// RdmaLinkAdd adds an rdma link for the specified type to the network device.
+func (h *Handle) RdmaLinkAdd(linkName string, linkType string, netdev string) error {
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_NEWLINK)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, nl.ZeroTerminated(linkName)))
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_LINK_TYPE, nl.ZeroTerminated(linkType)))
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_NDEV_NAME, nl.ZeroTerminated(netdev)))
+ _, err := req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go
index 845f41808..ffad5d398 100644
--- a/vendor/github.com/vishvananda/netlink/route.go
+++ b/vendor/github.com/vishvananda/netlink/route.go
@@ -41,6 +41,7 @@ type Route struct {
MultiPath []*NexthopInfo
Protocol RouteProtocol
Priority int
+ Family int
Table int
Type int
Tos int
@@ -49,6 +50,7 @@ type Route struct {
NewDst Destination
Encap Encap
Via Destination
+ Realm int
MTU int
Window int
Rtt int
@@ -94,6 +96,7 @@ func (r Route) String() string {
}
elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
+ elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm))
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
}
@@ -107,6 +110,7 @@ func (r Route) Equal(x Route) bool {
nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
r.Protocol == x.Protocol &&
r.Priority == x.Priority &&
+ r.Realm == x.Realm &&
r.Table == x.Table &&
r.Type == x.Type &&
r.Tos == x.Tos &&
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 32641cb0d..b059d4a9e 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -56,6 +56,7 @@ const (
RT_FILTER_PRIORITY
RT_FILTER_MARK
RT_FILTER_MASK
+ RT_FILTER_REALM
)
const (
@@ -151,7 +152,6 @@ func (e *MPLSEncap) Decode(buf []byte) error {
if len(buf) < 4 {
return fmt.Errorf("lack of bytes")
}
- native := nl.NativeEndian()
l := native.Uint16(buf)
if len(buf) < int(l) {
return fmt.Errorf("lack of bytes")
@@ -167,7 +167,6 @@ func (e *MPLSEncap) Decode(buf []byte) error {
func (e *MPLSEncap) Encode() ([]byte, error) {
s := nl.EncodeMPLSStack(e.Labels...)
- native := nl.NativeEndian()
hdr := make([]byte, 4)
native.PutUint16(hdr, uint16(len(s)+4))
native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST)
@@ -223,7 +222,6 @@ func (e *SEG6Encap) Decode(buf []byte) error {
if len(buf) < 4 {
return fmt.Errorf("lack of bytes")
}
- native := nl.NativeEndian()
// Get Length(l) & Type(typ) : 2 + 2 bytes
l := native.Uint16(buf)
if len(buf) < int(l) {
@@ -243,7 +241,6 @@ func (e *SEG6Encap) Decode(buf []byte) error {
}
func (e *SEG6Encap) Encode() ([]byte, error) {
s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments)
- native := nl.NativeEndian()
hdr := make([]byte, 4)
native.PutUint16(hdr, uint16(len(s)+4))
native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH)
@@ -253,7 +250,7 @@ func (e *SEG6Encap) String() string {
segs := make([]string, 0, len(e.Segments))
// append segment backwards (from n to 0) since seg#0 is the last segment.
for i := len(e.Segments); i > 0; i-- {
- segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
+ segs = append(segs, e.Segments[i-1].String())
}
str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode),
len(e.Segments), strings.Join(segs, " "))
@@ -304,7 +301,6 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
if err != nil {
return err
}
- native := nl.NativeEndian()
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.SEG6_LOCAL_ACTION:
@@ -334,7 +330,6 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
}
func (e *SEG6LocalEncap) Encode() ([]byte, error) {
var err error
- native := nl.NativeEndian()
res := make([]byte, 8)
native.PutUint16(res, 8) // length
native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION)
@@ -425,7 +420,7 @@ func (e *SEG6LocalEncap) String() string {
segs := make([]string, 0, len(e.Segments))
//append segment backwards (from n to 0) since seg#0 is the last segment.
for i := len(e.Segments); i > 0; i-- {
- segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
+ segs = append(segs, e.Segments[i-1].String())
}
strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
}
@@ -466,6 +461,152 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
return true
}
+// Encap BPF definitions
+type bpfObj struct {
+ progFd int
+ progName string
+}
+type BpfEncap struct {
+ progs [nl.LWT_BPF_MAX]bpfObj
+ headroom int
+}
+
+// SetProg adds a bpf function to the route via netlink RTA_ENCAP. The fd must be a bpf
+// program loaded with bpf(type=BPF_PROG_TYPE_LWT_*) matching the direction the program should
+// be applied to (LWT_BPF_IN, LWT_BPF_OUT, LWT_BPF_XMIT).
+func (e *BpfEncap) SetProg(mode, progFd int, progName string) error {
+ if progFd <= 0 {
+ return fmt.Errorf("lwt bpf SetProg: invalid fd")
+ }
+ if mode <= nl.LWT_BPF_UNSPEC || mode >= nl.LWT_BPF_XMIT_HEADROOM {
+ return fmt.Errorf("lwt bpf SetProg:invalid mode")
+ }
+ e.progs[mode].progFd = progFd
+ e.progs[mode].progName = fmt.Sprintf("%s[fd:%d]", progName, progFd)
+ return nil
+}
+
+// SetXmitHeadroom sets the xmit headroom (LWT_BPF_MAX_HEADROOM) via netlink RTA_ENCAP.
+// maximum headroom is LWT_BPF_MAX_HEADROOM
+func (e *BpfEncap) SetXmitHeadroom(headroom int) error {
+ if headroom > nl.LWT_BPF_MAX_HEADROOM || headroom < 0 {
+ return fmt.Errorf("invalid headroom size. range is 0 - %d", nl.LWT_BPF_MAX_HEADROOM)
+ }
+ e.headroom = headroom
+ return nil
+}
+
+func (e *BpfEncap) Type() int {
+ return nl.LWTUNNEL_ENCAP_BPF
+}
+func (e *BpfEncap) Decode(buf []byte) error {
+ if len(buf) < 4 {
+ return fmt.Errorf("lwt bpf decode: lack of bytes")
+ }
+ native := nl.NativeEndian()
+ attrs, err := nl.ParseRouteAttr(buf)
+ if err != nil {
+ return fmt.Errorf("lwt bpf decode: failed parsing attribute. err: %v", err)
+ }
+ for _, attr := range attrs {
+ if int(attr.Attr.Type) < 1 {
+ // nl.LWT_BPF_UNSPEC
+ continue
+ }
+ if int(attr.Attr.Type) > nl.LWT_BPF_MAX {
+ return fmt.Errorf("lwt bpf decode: received unknown attribute type: %d", attr.Attr.Type)
+ }
+ switch int(attr.Attr.Type) {
+ case nl.LWT_BPF_MAX_HEADROOM:
+ e.headroom = int(native.Uint32(attr.Value))
+ default:
+ bpfO := bpfObj{}
+ parsedAttrs, err := nl.ParseRouteAttr(attr.Value)
+ if err != nil {
+ return fmt.Errorf("lwt bpf decode: failed parsing route attribute")
+ }
+ for _, parsedAttr := range parsedAttrs {
+ switch int(parsedAttr.Attr.Type) {
+ case nl.LWT_BPF_PROG_FD:
+ bpfO.progFd = int(native.Uint32(parsedAttr.Value))
+ case nl.LWT_BPF_PROG_NAME:
+ bpfO.progName = string(parsedAttr.Value)
+ default:
+ return fmt.Errorf("lwt bpf decode: received unknown attribute: type: %d, len: %d", parsedAttr.Attr.Type, parsedAttr.Attr.Len)
+ }
+ }
+ e.progs[attr.Attr.Type] = bpfO
+ }
+ }
+ return nil
+}
+
+func (e *BpfEncap) Encode() ([]byte, error) {
+ buf := make([]byte, 0)
+ native = nl.NativeEndian()
+ for index, attr := range e.progs {
+ nlMsg := nl.NewRtAttr(index, []byte{})
+ if attr.progFd != 0 {
+ nlMsg.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(attr.progFd)))
+ }
+ if attr.progName != "" {
+ nlMsg.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(attr.progName))
+ }
+ if nlMsg.Len() > 4 {
+ buf = append(buf, nlMsg.Serialize()...)
+ }
+ }
+ if len(buf) <= 4 {
+ return nil, fmt.Errorf("lwt bpf encode: bpf obj definitions returned empty buffer")
+ }
+ if e.headroom > 0 {
+ hRoom := nl.NewRtAttr(nl.LWT_BPF_XMIT_HEADROOM, nl.Uint32Attr(uint32(e.headroom)))
+ buf = append(buf, hRoom.Serialize()...)
+ }
+ return buf, nil
+}
+
+func (e *BpfEncap) String() string {
+ progs := make([]string, 0)
+ for index, obj := range e.progs {
+ empty := bpfObj{}
+ switch index {
+ case nl.LWT_BPF_IN:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("in: %s", obj.progName))
+ }
+ case nl.LWT_BPF_OUT:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("out: %s", obj.progName))
+ }
+ case nl.LWT_BPF_XMIT:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("xmit: %s", obj.progName))
+ }
+ }
+ }
+ if e.headroom > 0 {
+ progs = append(progs, fmt.Sprintf("xmit headroom: %d", e.headroom))
+ }
+ return strings.Join(progs, " ")
+}
+
+func (e *BpfEncap) Equal(x Encap) bool {
+ o, ok := x.(*BpfEncap)
+ if !ok {
+ return false
+ }
+ if e.headroom != o.headroom {
+ return false
+ }
+ for i := range o.progs {
+ if o.progs[i] != e.progs[i] {
+ return false
+ }
+ }
+ return true
+}
+
type Via struct {
AddrFamily int
Addr net.IP
@@ -504,7 +645,6 @@ func (v *Via) Encode() ([]byte, error) {
}
func (v *Via) Decode(b []byte) error {
- native := nl.NativeEndian()
if len(b) < 6 {
return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
}
@@ -552,14 +692,14 @@ func (h *Handle) RouteAppend(route *Route) error {
// RouteAddEcmp will add a route to the system.
func RouteAddEcmp(route *Route) error {
- return pkgHandle.RouteAddEcmp(route)
+ return pkgHandle.RouteAddEcmp(route)
}
// RouteAddEcmp will add a route to the system.
func (h *Handle) RouteAddEcmp(route *Route) error {
- flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
- req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
- return h.routeHandle(route, req, nl.NewRtMsg())
+ flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
+ req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
+ return h.routeHandle(route, req, nl.NewRtMsg())
}
// RouteReplace will add a route to the system.
@@ -635,7 +775,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil {
return err
}
- rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
+ switch route.Encap.Type() {
+ case nl.LWTUNNEL_ENCAP_BPF:
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP|unix.NLA_F_NESTED, buf))
+ default:
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
+ }
+
}
if route.Src != nil {
@@ -748,6 +894,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
native.PutUint32(b, uint32(route.Priority))
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b))
}
+ if route.Realm > 0 {
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(route.Realm))
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_FLOW, b))
+ }
if route.Tos > 0 {
msg.Tos = uint8(route.Tos)
}
@@ -840,10 +991,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
req.AddData(attr)
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
+ b := make([]byte, 4)
native.PutUint32(b, uint32(route.LinkIndex))
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
@@ -919,6 +1067,8 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
continue
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
continue
+ case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
+ continue
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
continue
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
@@ -956,9 +1106,9 @@ func deserializeRoute(m []byte) (Route, error) {
Type: int(msg.Type),
Tos: int(msg.Tos),
Flags: int(msg.Flags),
+ Family: int(msg.Family),
}
- native := nl.NativeEndian()
var encap, encapType syscall.NetlinkRouteAttr
for _, attr := range attrs {
switch attr.Attr.Type {
@@ -985,6 +1135,8 @@ func deserializeRoute(m []byte) (Route, error) {
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_PRIORITY:
route.Priority = int(native.Uint32(attr.Value[0:4]))
+ case unix.RTA_FLOW:
+ route.Realm = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_TABLE:
route.Table = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_MULTIPATH:
@@ -1140,6 +1292,11 @@ func deserializeRoute(m []byte) (Route, error) {
if err := e.Decode(encap.Value); err != nil {
return route, err
}
+ case nl.LWTUNNEL_ENCAP_BPF:
+ e = &BpfEncap{}
+ if err := e.Decode(encap.Value); err != nil {
+ return route, err
+ }
}
route.Encap = e
}
@@ -1150,6 +1307,8 @@ func deserializeRoute(m []byte) (Route, error) {
// RouteGetOptions contains a set of options to use with
// RouteGetWithOptions
type RouteGetOptions struct {
+ Iif string
+ Oif string
VrfName string
SrcAddr net.IP
}
@@ -1198,10 +1357,31 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
if err != nil {
return nil, err
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
+ }
+
+ if len(options.Iif) > 0 {
+ link, err := LinkByName(options.Iif)
+ if err != nil {
+ return nil, err
+ }
+
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
+ }
+
+ if len(options.Oif) > 0 {
+ link, err := LinkByName(options.Oif)
+ if err != nil {
+ return nil, err
+ }
+
+ b := make([]byte, 4)
native.PutUint32(b, uint32(link.Attrs().Index))
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
@@ -1298,7 +1478,8 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -1313,22 +1494,22 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
route, err := deserializeRoute(m.Data)
if err != nil {
if cberr != nil {
cberr(err)
}
- return
+ continue
}
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
}
diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go
index 95f2facfb..9b7b0af49 100644
--- a/vendor/github.com/vishvananda/netlink/rule.go
+++ b/vendor/github.com/vishvananda/netlink/rule.go
@@ -28,7 +28,18 @@ type Rule struct {
}
func (r Rule) String() string {
- return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table)
+ from := "all"
+ if r.Src != nil && r.Src.String() != "<nil>" {
+ from = r.Src.String()
+ }
+
+ to := "all"
+ if r.Dst != nil && r.Dst.String() != "<nil>" {
+ to = r.Dst.String()
+ }
+
+ return fmt.Sprintf("ip rule %d: from %s to %s table %d",
+ r.Priority, from, to, r.Table)
}
// NewRule return empty rules.
diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go
index 40474f30e..9c426cbd3 100644
--- a/vendor/github.com/vishvananda/netlink/rule_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rule_linux.go
@@ -97,8 +97,6 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
req.AddData(rtAttrs[i])
}
- native := nl.NativeEndian()
-
if rule.Priority >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Priority))
@@ -199,7 +197,6 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
return nil, err
}
- native := nl.NativeEndian()
var res = make([]Rule, 0)
for i := range msgs {
msg := nl.DeserializeRtMsg(msgs[i])
@@ -232,7 +229,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
case nl.FRA_FWMASK:
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_TUN_ID:
- rule.TunID = uint(native.Uint64(attrs[j].Value[0:4]))
+ rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
case nl.FRA_IIFNAME:
rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
case nl.FRA_OIFNAME:
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index 9b0f4a081..b881fe496 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -172,12 +172,56 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
return sock, nil
}
-// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type.
+// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
- s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
+ var result []*InetDiagTCPInfoResp
+ err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
+ sockInfo := &Socket{}
+ if err := sockInfo.deserialize(m.Data); err != nil {
+ return err
+ }
+ attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
+ if err != nil {
+ return err
+ }
+
+ res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
+ if err != nil {
+ return err
+ }
+
+ result = append(result, res)
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
+func SocketDiagTCP(family uint8) ([]*Socket, error) {
+ var result []*Socket
+ err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
+ sockInfo := &Socket{}
+ if err := sockInfo.deserialize(m.Data); err != nil {
+ return err
+ }
+ result = append(result, sockInfo)
+ return nil
+ })
if err != nil {
return nil, err
}
+ return result, nil
+}
+
+// socketDiagTCPExecutor requests INET_DIAG_INFO for TCP protocol for specified family type.
+func socketDiagTCPExecutor(family uint8, receiver func(syscall.NetlinkMessage) error) error {
+ s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
+ if err != nil {
+ return err
+ }
defer s.Close()
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
@@ -189,18 +233,17 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
})
s.Send(req)
- var result []*InetDiagTCPInfoResp
loop:
for {
msgs, from, err := s.Receive()
if err != nil {
- return nil, err
+ return err
}
if from.Pid != nl.PidKernel {
- return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
}
if len(msgs) == 0 {
- return nil, errors.New("no message nor error from netlink")
+ return errors.New("no message nor error from netlink")
}
for _, m := range msgs {
@@ -208,28 +251,15 @@ loop:
case unix.NLMSG_DONE:
break loop
case unix.NLMSG_ERROR:
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
- return nil, syscall.Errno(-error)
+ return syscall.Errno(-error)
}
- sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return nil, err
+ if err := receiver(m); err != nil {
+ return err
}
- attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
- if err != nil {
- return nil, err
- }
-
- res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
- if err != nil {
- return nil, err
- }
-
- result = append(result, res)
}
}
- return result, nil
+ return nil
}
func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
index 5b1b6c31a..3b37b87d3 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -111,7 +111,7 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
// A state with spi 0 can't be deleted so don't allow it to be set
if state.Spi == 0 {
- return fmt.Errorf("Spi must be set when adding xfrm state.")
+ return fmt.Errorf("Spi must be set when adding xfrm state")
}
req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
index c67e9b7f5..e644d9b2f 100644
--- a/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -719,7 +719,15 @@ func (sc *serverConn) canonicalHeader(v string) string {
sc.canonHeader = make(map[string]string)
}
cv = http.CanonicalHeaderKey(v)
- sc.canonHeader[v] = cv
+ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
+ // entries in the canonHeader cache. This should be larger than the number
+ // of unique, uncommon header keys likely to be sent by the peer, while not
+ // so high as to permit unreasonable memory usage if the peer sends an unbounded
+ // number of unique header keys.
+ const maxCachedCanonicalHeaders = 32
+ if len(sc.canonHeader) < maxCachedCanonicalHeaders {
+ sc.canonHeader[v] = cv
+ }
return cv
}
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go
index b5e2ac64d..f135b0f75 100644
--- a/vendor/golang.org/x/net/http2/transport.go
+++ b/vendor/golang.org/x/net/http2/transport.go
@@ -1124,36 +1124,49 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
}
}
+ handleResponseHeaders := func() (*http.Response, error) {
+ res := cs.res
+ if res.StatusCode > 299 {
+ // On error or status code 3xx, 4xx, 5xx, etc abort any
+ // ongoing write, assuming that the server doesn't care
+ // about our request body. If the server replied with 1xx or
+ // 2xx, however, then assume the server DOES potentially
+ // want our body (e.g. full-duplex streaming:
+ // golang.org/issue/13444). If it turns out the server
+ // doesn't, they'll RST_STREAM us soon enough. This is a
+ // heuristic to avoid adding knobs to Transport. Hopefully
+ // we can keep it.
+ cs.abortRequestBodyWrite()
+ }
+ res.Request = req
+ res.TLS = cc.tlsState
+ if res.Body == noBody && actualContentLength(req) == 0 {
+ // If there isn't a request or response body still being
+ // written, then wait for the stream to be closed before
+ // RoundTrip returns.
+ if err := waitDone(); err != nil {
+ return nil, err
+ }
+ }
+ return res, nil
+ }
+
for {
select {
case <-cs.respHeaderRecv:
- res := cs.res
- if res.StatusCode > 299 {
- // On error or status code 3xx, 4xx, 5xx, etc abort any
- // ongoing write, assuming that the server doesn't care
- // about our request body. If the server replied with 1xx or
- // 2xx, however, then assume the server DOES potentially
- // want our body (e.g. full-duplex streaming:
- // golang.org/issue/13444). If it turns out the server
- // doesn't, they'll RST_STREAM us soon enough. This is a
- // heuristic to avoid adding knobs to Transport. Hopefully
- // we can keep it.
- cs.abortRequestBodyWrite()
- }
- res.Request = req
- res.TLS = cc.tlsState
- if res.Body == noBody && actualContentLength(req) == 0 {
- // If there isn't a request or response body still being
- // written, then wait for the stream to be closed before
- // RoundTrip returns.
- if err := waitDone(); err != nil {
- return nil, err
- }
- }
- return res, nil
+ return handleResponseHeaders()
case <-cs.abort:
- waitDone()
- return nil, cs.abortErr
+ select {
+ case <-cs.respHeaderRecv:
+ // If both cs.respHeaderRecv and cs.abort are signaling,
+ // pick respHeaderRecv. The server probably wrote the
+ // response and immediately reset the stream.
+ // golang.org/issue/49645
+ return handleResponseHeaders()
+ default:
+ waitDone()
+ return nil, cs.abortErr
+ }
case <-ctx.Done():
err := ctx.Err()
cs.abortStream(err)
@@ -1239,12 +1252,12 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
}
continueTimeout := cc.t.expectContinueTimeout()
- if continueTimeout != 0 &&
- !httpguts.HeaderValuesContainsToken(
- req.Header["Expect"],
- "100-continue") {
- continueTimeout = 0
- cs.on100 = make(chan struct{}, 1)
+ if continueTimeout != 0 {
+ if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") {
+ continueTimeout = 0
+ } else {
+ cs.on100 = make(chan struct{}, 1)
+ }
}
// Past this point (where we send request headers), it is possible for
@@ -1313,6 +1326,7 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
case <-respHeaderTimer:
return errTimeout
case <-respHeaderRecv:
+ respHeaderRecv = nil
respHeaderTimer = nil // keep waiting for END_STREAM
case <-cs.abort:
return cs.abortErr
diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go
index f24d2b1e7..c7cd00173 100644
--- a/vendor/golang.org/x/net/http2/writesched.go
+++ b/vendor/golang.org/x/net/http2/writesched.go
@@ -32,7 +32,8 @@ type WriteScheduler interface {
// Pop dequeues the next frame to write. Returns false if no frames can
// be written. Frames with a given wr.StreamID() are Pop'd in the same
- // order they are Push'd. No frames should be discarded except by CloseStream.
+ // order they are Push'd, except RST_STREAM frames. No frames should be
+ // discarded except by CloseStream.
Pop() (wr FrameWriteRequest, ok bool)
}
@@ -52,6 +53,7 @@ type FrameWriteRequest struct {
// stream is the stream on which this frame will be written.
// nil for non-stream frames like PING and SETTINGS.
+ // nil for RST_STREAM streams, which use the StreamError.StreamID field instead.
stream *stream
// done, if non-nil, must be a buffered channel with space for
diff --git a/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go
index 9a7b9e581..f2e55e05c 100644
--- a/vendor/golang.org/x/net/http2/writesched_random.go
+++ b/vendor/golang.org/x/net/http2/writesched_random.go
@@ -45,11 +45,11 @@ func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityP
}
func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
- id := wr.StreamID()
- if id == 0 {
+ if wr.isControl() {
ws.zero.push(wr)
return
}
+ id := wr.StreamID()
q, ok := ws.sq[id]
if !ok {
q = ws.queuePool.get()
@@ -59,7 +59,7 @@ func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
}
func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
- // Control frames first.
+ // Control and RST_STREAM frames first.
if !ws.zero.empty() {
return ws.zero.shift(), true
}
diff --git a/vendor/golang.org/x/net/internal/socks/client.go b/vendor/golang.org/x/net/internal/socks/client.go
deleted file mode 100644
index 3d6f516a5..000000000
--- a/vendor/golang.org/x/net/internal/socks/client.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package socks
-
-import (
- "context"
- "errors"
- "io"
- "net"
- "strconv"
- "time"
-)
-
-var (
- noDeadline = time.Time{}
- aLongTimeAgo = time.Unix(1, 0)
-)
-
-func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
- host, port, err := splitHostPort(address)
- if err != nil {
- return nil, err
- }
- if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
- c.SetDeadline(deadline)
- defer c.SetDeadline(noDeadline)
- }
- if ctx != context.Background() {
- errCh := make(chan error, 1)
- done := make(chan struct{})
- defer func() {
- close(done)
- if ctxErr == nil {
- ctxErr = <-errCh
- }
- }()
- go func() {
- select {
- case <-ctx.Done():
- c.SetDeadline(aLongTimeAgo)
- errCh <- ctx.Err()
- case <-done:
- errCh <- nil
- }
- }()
- }
-
- b := make([]byte, 0, 6+len(host)) // the size here is just an estimate
- b = append(b, Version5)
- if len(d.AuthMethods) == 0 || d.Authenticate == nil {
- b = append(b, 1, byte(AuthMethodNotRequired))
- } else {
- ams := d.AuthMethods
- if len(ams) > 255 {
- return nil, errors.New("too many authentication methods")
- }
- b = append(b, byte(len(ams)))
- for _, am := range ams {
- b = append(b, byte(am))
- }
- }
- if _, ctxErr = c.Write(b); ctxErr != nil {
- return
- }
-
- if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
- return
- }
- if b[0] != Version5 {
- return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
- }
- am := AuthMethod(b[1])
- if am == AuthMethodNoAcceptableMethods {
- return nil, errors.New("no acceptable authentication methods")
- }
- if d.Authenticate != nil {
- if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
- return
- }
- }
-
- b = b[:0]
- b = append(b, Version5, byte(d.cmd), 0)
- if ip := net.ParseIP(host); ip != nil {
- if ip4 := ip.To4(); ip4 != nil {
- b = append(b, AddrTypeIPv4)
- b = append(b, ip4...)
- } else if ip6 := ip.To16(); ip6 != nil {
- b = append(b, AddrTypeIPv6)
- b = append(b, ip6...)
- } else {
- return nil, errors.New("unknown address type")
- }
- } else {
- if len(host) > 255 {
- return nil, errors.New("FQDN too long")
- }
- b = append(b, AddrTypeFQDN)
- b = append(b, byte(len(host)))
- b = append(b, host...)
- }
- b = append(b, byte(port>>8), byte(port))
- if _, ctxErr = c.Write(b); ctxErr != nil {
- return
- }
-
- if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
- return
- }
- if b[0] != Version5 {
- return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
- }
- if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded {
- return nil, errors.New("unknown error " + cmdErr.String())
- }
- if b[2] != 0 {
- return nil, errors.New("non-zero reserved field")
- }
- l := 2
- var a Addr
- switch b[3] {
- case AddrTypeIPv4:
- l += net.IPv4len
- a.IP = make(net.IP, net.IPv4len)
- case AddrTypeIPv6:
- l += net.IPv6len
- a.IP = make(net.IP, net.IPv6len)
- case AddrTypeFQDN:
- if _, err := io.ReadFull(c, b[:1]); err != nil {
- return nil, err
- }
- l += int(b[0])
- default:
- return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
- }
- if cap(b) < l {
- b = make([]byte, l)
- } else {
- b = b[:l]
- }
- if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
- return
- }
- if a.IP != nil {
- copy(a.IP, b)
- } else {
- a.Name = string(b[:len(b)-2])
- }
- a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
- return &a, nil
-}
-
-func splitHostPort(address string) (string, int, error) {
- host, port, err := net.SplitHostPort(address)
- if err != nil {
- return "", 0, err
- }
- portnum, err := strconv.Atoi(port)
- if err != nil {
- return "", 0, err
- }
- if 1 > portnum || portnum > 0xffff {
- return "", 0, errors.New("port number out of range " + port)
- }
- return host, portnum, nil
-}
diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go
deleted file mode 100644
index 97db2340e..000000000
--- a/vendor/golang.org/x/net/internal/socks/socks.go
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package socks provides a SOCKS version 5 client implementation.
-//
-// SOCKS protocol version 5 is defined in RFC 1928.
-// Username/Password authentication for SOCKS version 5 is defined in
-// RFC 1929.
-package socks
-
-import (
- "context"
- "errors"
- "io"
- "net"
- "strconv"
-)
-
-// A Command represents a SOCKS command.
-type Command int
-
-func (cmd Command) String() string {
- switch cmd {
- case CmdConnect:
- return "socks connect"
- case cmdBind:
- return "socks bind"
- default:
- return "socks " + strconv.Itoa(int(cmd))
- }
-}
-
-// An AuthMethod represents a SOCKS authentication method.
-type AuthMethod int
-
-// A Reply represents a SOCKS command reply code.
-type Reply int
-
-func (code Reply) String() string {
- switch code {
- case StatusSucceeded:
- return "succeeded"
- case 0x01:
- return "general SOCKS server failure"
- case 0x02:
- return "connection not allowed by ruleset"
- case 0x03:
- return "network unreachable"
- case 0x04:
- return "host unreachable"
- case 0x05:
- return "connection refused"
- case 0x06:
- return "TTL expired"
- case 0x07:
- return "command not supported"
- case 0x08:
- return "address type not supported"
- default:
- return "unknown code: " + strconv.Itoa(int(code))
- }
-}
-
-// Wire protocol constants.
-const (
- Version5 = 0x05
-
- AddrTypeIPv4 = 0x01
- AddrTypeFQDN = 0x03
- AddrTypeIPv6 = 0x04
-
- CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
- cmdBind Command = 0x02 // establishes a passive-open forward proxy connection
-
- AuthMethodNotRequired AuthMethod = 0x00 // no authentication required
- AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password
- AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods
-
- StatusSucceeded Reply = 0x00
-)
-
-// An Addr represents a SOCKS-specific address.
-// Either Name or IP is used exclusively.
-type Addr struct {
- Name string // fully-qualified domain name
- IP net.IP
- Port int
-}
-
-func (a *Addr) Network() string { return "socks" }
-
-func (a *Addr) String() string {
- if a == nil {
- return "<nil>"
- }
- port := strconv.Itoa(a.Port)
- if a.IP == nil {
- return net.JoinHostPort(a.Name, port)
- }
- return net.JoinHostPort(a.IP.String(), port)
-}
-
-// A Conn represents a forward proxy connection.
-type Conn struct {
- net.Conn
-
- boundAddr net.Addr
-}
-
-// BoundAddr returns the address assigned by the proxy server for
-// connecting to the command target address from the proxy server.
-func (c *Conn) BoundAddr() net.Addr {
- if c == nil {
- return nil
- }
- return c.boundAddr
-}
-
-// A Dialer holds SOCKS-specific options.
-type Dialer struct {
- cmd Command // either CmdConnect or cmdBind
- proxyNetwork string // network between a proxy server and a client
- proxyAddress string // proxy server address
-
- // ProxyDial specifies the optional dial function for
- // establishing the transport connection.
- ProxyDial func(context.Context, string, string) (net.Conn, error)
-
- // AuthMethods specifies the list of request authentication
- // methods.
- // If empty, SOCKS client requests only AuthMethodNotRequired.
- AuthMethods []AuthMethod
-
- // Authenticate specifies the optional authentication
- // function. It must be non-nil when AuthMethods is not empty.
- // It must return an error when the authentication is failed.
- Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
-}
-
-// DialContext connects to the provided address on the provided
-// network.
-//
-// The returned error value may be a net.OpError. When the Op field of
-// net.OpError contains "socks", the Source field contains a proxy
-// server address and the Addr field contains a command target
-// address.
-//
-// See func Dial of the net package of standard library for a
-// description of the network and address parameters.
-func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
- if err := d.validateTarget(network, address); err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- if ctx == nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
- }
- var err error
- var c net.Conn
- if d.ProxyDial != nil {
- c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
- } else {
- var dd net.Dialer
- c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
- }
- if err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- a, err := d.connect(ctx, c, address)
- if err != nil {
- c.Close()
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- return &Conn{Conn: c, boundAddr: a}, nil
-}
-
-// DialWithConn initiates a connection from SOCKS server to the target
-// network and address using the connection c that is already
-// connected to the SOCKS server.
-//
-// It returns the connection's local address assigned by the SOCKS
-// server.
-func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) {
- if err := d.validateTarget(network, address); err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- if ctx == nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
- }
- a, err := d.connect(ctx, c, address)
- if err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- return a, nil
-}
-
-// Dial connects to the provided address on the provided network.
-//
-// Unlike DialContext, it returns a raw transport connection instead
-// of a forward proxy connection.
-//
-// Deprecated: Use DialContext or DialWithConn instead.
-func (d *Dialer) Dial(network, address string) (net.Conn, error) {
- if err := d.validateTarget(network, address); err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- var err error
- var c net.Conn
- if d.ProxyDial != nil {
- c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress)
- } else {
- c, err = net.Dial(d.proxyNetwork, d.proxyAddress)
- }
- if err != nil {
- proxy, dst, _ := d.pathAddrs(address)
- return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
- }
- if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil {
- c.Close()
- return nil, err
- }
- return c, nil
-}
-
-func (d *Dialer) validateTarget(network, address string) error {
- switch network {
- case "tcp", "tcp6", "tcp4":
- default:
- return errors.New("network not implemented")
- }
- switch d.cmd {
- case CmdConnect, cmdBind:
- default:
- return errors.New("command not implemented")
- }
- return nil
-}
-
-func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
- for i, s := range []string{d.proxyAddress, address} {
- host, port, err := splitHostPort(s)
- if err != nil {
- return nil, nil, err
- }
- a := &Addr{Port: port}
- a.IP = net.ParseIP(host)
- if a.IP == nil {
- a.Name = host
- }
- if i == 0 {
- proxy = a
- } else {
- dst = a
- }
- }
- return
-}
-
-// NewDialer returns a new Dialer that dials through the provided
-// proxy server's network and address.
-func NewDialer(network, address string) *Dialer {
- return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect}
-}
-
-const (
- authUsernamePasswordVersion = 0x01
- authStatusSucceeded = 0x00
-)
-
-// UsernamePassword are the credentials for the username/password
-// authentication method.
-type UsernamePassword struct {
- Username string
- Password string
-}
-
-// Authenticate authenticates a pair of username and password with the
-// proxy server.
-func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error {
- switch auth {
- case AuthMethodNotRequired:
- return nil
- case AuthMethodUsernamePassword:
- if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 {
- return errors.New("invalid username/password")
- }
- b := []byte{authUsernamePasswordVersion}
- b = append(b, byte(len(up.Username)))
- b = append(b, up.Username...)
- b = append(b, byte(len(up.Password)))
- b = append(b, up.Password...)
- // TODO(mikio): handle IO deadlines and cancelation if
- // necessary
- if _, err := rw.Write(b); err != nil {
- return err
- }
- if _, err := io.ReadFull(rw, b[:2]); err != nil {
- return err
- }
- if b[0] != authUsernamePasswordVersion {
- return errors.New("invalid username/password version")
- }
- if b[1] != authStatusSucceeded {
- return errors.New("username/password authentication failed")
- }
- return nil
- }
- return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
-}
diff --git a/vendor/golang.org/x/net/proxy/dial.go b/vendor/golang.org/x/net/proxy/dial.go
deleted file mode 100644
index 811c2e4e9..000000000
--- a/vendor/golang.org/x/net/proxy/dial.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 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 proxy
-
-import (
- "context"
- "net"
-)
-
-// A ContextDialer dials using a context.
-type ContextDialer interface {
- DialContext(ctx context.Context, network, address string) (net.Conn, error)
-}
-
-// Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment.
-//
-// The passed ctx is only used for returning the Conn, not the lifetime of the Conn.
-//
-// Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer
-// can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout.
-//
-// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed.
-func Dial(ctx context.Context, network, address string) (net.Conn, error) {
- d := FromEnvironment()
- if xd, ok := d.(ContextDialer); ok {
- return xd.DialContext(ctx, network, address)
- }
- return dialContext(ctx, d, network, address)
-}
-
-// WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout
-// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed.
-func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) {
- var (
- conn net.Conn
- done = make(chan struct{}, 1)
- err error
- )
- go func() {
- conn, err = d.Dial(network, address)
- close(done)
- if conn != nil && ctx.Err() != nil {
- conn.Close()
- }
- }()
- select {
- case <-ctx.Done():
- err = ctx.Err()
- case <-done:
- }
- return conn, err
-}
diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go
deleted file mode 100644
index 3d66bdef9..000000000
--- a/vendor/golang.org/x/net/proxy/direct.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2011 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 proxy
-
-import (
- "context"
- "net"
-)
-
-type direct struct{}
-
-// Direct implements Dialer by making network connections directly using net.Dial or net.DialContext.
-var Direct = direct{}
-
-var (
- _ Dialer = Direct
- _ ContextDialer = Direct
-)
-
-// Dial directly invokes net.Dial with the supplied parameters.
-func (direct) Dial(network, addr string) (net.Conn, error) {
- return net.Dial(network, addr)
-}
-
-// DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters.
-func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
- var d net.Dialer
- return d.DialContext(ctx, network, addr)
-}
diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go
deleted file mode 100644
index 573fe79e8..000000000
--- a/vendor/golang.org/x/net/proxy/per_host.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2011 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 proxy
-
-import (
- "context"
- "net"
- "strings"
-)
-
-// A PerHost directs connections to a default Dialer unless the host name
-// requested matches one of a number of exceptions.
-type PerHost struct {
- def, bypass Dialer
-
- bypassNetworks []*net.IPNet
- bypassIPs []net.IP
- bypassZones []string
- bypassHosts []string
-}
-
-// NewPerHost returns a PerHost Dialer that directs connections to either
-// defaultDialer or bypass, depending on whether the connection matches one of
-// the configured rules.
-func NewPerHost(defaultDialer, bypass Dialer) *PerHost {
- return &PerHost{
- def: defaultDialer,
- bypass: bypass,
- }
-}
-
-// Dial connects to the address addr on the given network through either
-// defaultDialer or bypass.
-func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) {
- host, _, err := net.SplitHostPort(addr)
- if err != nil {
- return nil, err
- }
-
- return p.dialerForRequest(host).Dial(network, addr)
-}
-
-// DialContext connects to the address addr on the given network through either
-// defaultDialer or bypass.
-func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) {
- host, _, err := net.SplitHostPort(addr)
- if err != nil {
- return nil, err
- }
- d := p.dialerForRequest(host)
- if x, ok := d.(ContextDialer); ok {
- return x.DialContext(ctx, network, addr)
- }
- return dialContext(ctx, d, network, addr)
-}
-
-func (p *PerHost) dialerForRequest(host string) Dialer {
- if ip := net.ParseIP(host); ip != nil {
- for _, net := range p.bypassNetworks {
- if net.Contains(ip) {
- return p.bypass
- }
- }
- for _, bypassIP := range p.bypassIPs {
- if bypassIP.Equal(ip) {
- return p.bypass
- }
- }
- return p.def
- }
-
- for _, zone := range p.bypassZones {
- if strings.HasSuffix(host, zone) {
- return p.bypass
- }
- if host == zone[1:] {
- // For a zone ".example.com", we match "example.com"
- // too.
- return p.bypass
- }
- }
- for _, bypassHost := range p.bypassHosts {
- if bypassHost == host {
- return p.bypass
- }
- }
- return p.def
-}
-
-// AddFromString parses a string that contains comma-separated values
-// specifying hosts that should use the bypass proxy. Each value is either an
-// IP address, a CIDR range, a zone (*.example.com) or a host name
-// (localhost). A best effort is made to parse the string and errors are
-// ignored.
-func (p *PerHost) AddFromString(s string) {
- hosts := strings.Split(s, ",")
- for _, host := range hosts {
- host = strings.TrimSpace(host)
- if len(host) == 0 {
- continue
- }
- if strings.Contains(host, "/") {
- // We assume that it's a CIDR address like 127.0.0.0/8
- if _, net, err := net.ParseCIDR(host); err == nil {
- p.AddNetwork(net)
- }
- continue
- }
- if ip := net.ParseIP(host); ip != nil {
- p.AddIP(ip)
- continue
- }
- if strings.HasPrefix(host, "*.") {
- p.AddZone(host[1:])
- continue
- }
- p.AddHost(host)
- }
-}
-
-// AddIP specifies an IP address that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match an IP.
-func (p *PerHost) AddIP(ip net.IP) {
- p.bypassIPs = append(p.bypassIPs, ip)
-}
-
-// AddNetwork specifies an IP range that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match.
-func (p *PerHost) AddNetwork(net *net.IPNet) {
- p.bypassNetworks = append(p.bypassNetworks, net)
-}
-
-// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
-// "example.com" matches "example.com" and all of its subdomains.
-func (p *PerHost) AddZone(zone string) {
- if strings.HasSuffix(zone, ".") {
- zone = zone[:len(zone)-1]
- }
- if !strings.HasPrefix(zone, ".") {
- zone = "." + zone
- }
- p.bypassZones = append(p.bypassZones, zone)
-}
-
-// AddHost specifies a host name that will use the bypass proxy.
-func (p *PerHost) AddHost(host string) {
- if strings.HasSuffix(host, ".") {
- host = host[:len(host)-1]
- }
- p.bypassHosts = append(p.bypassHosts, host)
-}
diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go
deleted file mode 100644
index 9ff4b9a77..000000000
--- a/vendor/golang.org/x/net/proxy/proxy.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2011 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 proxy provides support for a variety of protocols to proxy network
-// data.
-package proxy // import "golang.org/x/net/proxy"
-
-import (
- "errors"
- "net"
- "net/url"
- "os"
- "sync"
-)
-
-// A Dialer is a means to establish a connection.
-// Custom dialers should also implement ContextDialer.
-type Dialer interface {
- // Dial connects to the given address via the proxy.
- Dial(network, addr string) (c net.Conn, err error)
-}
-
-// Auth contains authentication parameters that specific Dialers may require.
-type Auth struct {
- User, Password string
-}
-
-// FromEnvironment returns the dialer specified by the proxy-related
-// variables in the environment and makes underlying connections
-// directly.
-func FromEnvironment() Dialer {
- return FromEnvironmentUsing(Direct)
-}
-
-// FromEnvironmentUsing returns the dialer specify by the proxy-related
-// variables in the environment and makes underlying connections
-// using the provided forwarding Dialer (for instance, a *net.Dialer
-// with desired configuration).
-func FromEnvironmentUsing(forward Dialer) Dialer {
- allProxy := allProxyEnv.Get()
- if len(allProxy) == 0 {
- return forward
- }
-
- proxyURL, err := url.Parse(allProxy)
- if err != nil {
- return forward
- }
- proxy, err := FromURL(proxyURL, forward)
- if err != nil {
- return forward
- }
-
- noProxy := noProxyEnv.Get()
- if len(noProxy) == 0 {
- return proxy
- }
-
- perHost := NewPerHost(proxy, forward)
- perHost.AddFromString(noProxy)
- return perHost
-}
-
-// proxySchemes is a map from URL schemes to a function that creates a Dialer
-// from a URL with such a scheme.
-var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error)
-
-// RegisterDialerType takes a URL scheme and a function to generate Dialers from
-// a URL with that scheme and a forwarding Dialer. Registered schemes are used
-// by FromURL.
-func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) {
- if proxySchemes == nil {
- proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error))
- }
- proxySchemes[scheme] = f
-}
-
-// FromURL returns a Dialer given a URL specification and an underlying
-// Dialer for it to make network requests.
-func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
- var auth *Auth
- if u.User != nil {
- auth = new(Auth)
- auth.User = u.User.Username()
- if p, ok := u.User.Password(); ok {
- auth.Password = p
- }
- }
-
- switch u.Scheme {
- case "socks5", "socks5h":
- addr := u.Hostname()
- port := u.Port()
- if port == "" {
- port = "1080"
- }
- return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward)
- }
-
- // If the scheme doesn't match any of the built-in schemes, see if it
- // was registered by another package.
- if proxySchemes != nil {
- if f, ok := proxySchemes[u.Scheme]; ok {
- return f(u, forward)
- }
- }
-
- return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
-}
-
-var (
- allProxyEnv = &envOnce{
- names: []string{"ALL_PROXY", "all_proxy"},
- }
- noProxyEnv = &envOnce{
- names: []string{"NO_PROXY", "no_proxy"},
- }
-)
-
-// envOnce looks up an environment variable (optionally by multiple
-// names) once. It mitigates expensive lookups on some platforms
-// (e.g. Windows).
-// (Borrowed from net/http/transport.go)
-type envOnce struct {
- names []string
- once sync.Once
- val string
-}
-
-func (e *envOnce) Get() string {
- e.once.Do(e.init)
- return e.val
-}
-
-func (e *envOnce) init() {
- for _, n := range e.names {
- e.val = os.Getenv(n)
- if e.val != "" {
- return
- }
- }
-}
-
-// reset is used by tests
-func (e *envOnce) reset() {
- e.once = sync.Once{}
- e.val = ""
-}
diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go
deleted file mode 100644
index c91651f96..000000000
--- a/vendor/golang.org/x/net/proxy/socks5.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2011 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 proxy
-
-import (
- "context"
- "net"
-
- "golang.org/x/net/internal/socks"
-)
-
-// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given
-// address with an optional username and password.
-// See RFC 1928 and RFC 1929.
-func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) {
- d := socks.NewDialer(network, address)
- if forward != nil {
- if f, ok := forward.(ContextDialer); ok {
- d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) {
- return f.DialContext(ctx, network, address)
- }
- } else {
- d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) {
- return dialContext(ctx, forward, network, address)
- }
- }
- }
- if auth != nil {
- up := socks.UsernamePassword{
- Username: auth.User,
- Password: auth.Password,
- }
- d.AuthMethods = []socks.AuthMethod{
- socks.AuthMethodNotRequired,
- socks.AuthMethodUsernamePassword,
- }
- d.Authenticate = up.Authenticate
- }
- return d, nil
-}
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go
index bcc45d108..4e5420586 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -741,6 +741,7 @@ const (
ETH_P_QINQ2 = 0x9200
ETH_P_QINQ3 = 0x9300
ETH_P_RARP = 0x8035
+ ETH_P_REALTEK = 0x8899
ETH_P_SCA = 0x6007
ETH_P_SLOW = 0x8809
ETH_P_SNAP = 0x5
@@ -810,10 +811,12 @@ const (
FAN_EPIDFD = -0x2
FAN_EVENT_INFO_TYPE_DFID = 0x3
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
+ FAN_EVENT_INFO_TYPE_ERROR = 0x5
FAN_EVENT_INFO_TYPE_FID = 0x1
FAN_EVENT_INFO_TYPE_PIDFD = 0x4
FAN_EVENT_METADATA_LEN = 0x18
FAN_EVENT_ON_CHILD = 0x8000000
+ FAN_FS_ERROR = 0x8000
FAN_MARK_ADD = 0x1
FAN_MARK_DONT_FOLLOW = 0x4
FAN_MARK_FILESYSTEM = 0x100
@@ -1827,6 +1830,8 @@ const (
PERF_MEM_BLK_DATA = 0x2
PERF_MEM_BLK_NA = 0x1
PERF_MEM_BLK_SHIFT = 0x28
+ PERF_MEM_HOPS_0 = 0x1
+ PERF_MEM_HOPS_SHIFT = 0x2b
PERF_MEM_LOCK_LOCKED = 0x2
PERF_MEM_LOCK_NA = 0x1
PERF_MEM_LOCK_SHIFT = 0x18
@@ -1986,6 +1991,9 @@ const (
PR_SCHED_CORE_CREATE = 0x1
PR_SCHED_CORE_GET = 0x0
PR_SCHED_CORE_MAX = 0x4
+ PR_SCHED_CORE_SCOPE_PROCESS_GROUP = 0x2
+ PR_SCHED_CORE_SCOPE_THREAD = 0x0
+ PR_SCHED_CORE_SCOPE_THREAD_GROUP = 0x1
PR_SCHED_CORE_SHARE_FROM = 0x3
PR_SCHED_CORE_SHARE_TO = 0x2
PR_SET_CHILD_SUBREAPER = 0x24
@@ -2167,12 +2175,23 @@ const (
RTCF_NAT = 0x800000
RTCF_VALVE = 0x200000
RTC_AF = 0x20
+ RTC_BSM_DIRECT = 0x1
+ RTC_BSM_DISABLED = 0x0
+ RTC_BSM_LEVEL = 0x2
+ RTC_BSM_STANDBY = 0x3
RTC_FEATURE_ALARM = 0x0
+ RTC_FEATURE_ALARM_RES_2S = 0x3
RTC_FEATURE_ALARM_RES_MINUTE = 0x1
- RTC_FEATURE_CNT = 0x3
+ RTC_FEATURE_BACKUP_SWITCH_MODE = 0x6
+ RTC_FEATURE_CNT = 0x7
+ RTC_FEATURE_CORRECTION = 0x5
RTC_FEATURE_NEED_WEEK_DAY = 0x2
+ RTC_FEATURE_UPDATE_INTERRUPT = 0x4
RTC_IRQF = 0x80
RTC_MAX_FREQ = 0x2000
+ RTC_PARAM_BACKUP_SWITCH_MODE = 0x2
+ RTC_PARAM_CORRECTION = 0x1
+ RTC_PARAM_FEATURES = 0x0
RTC_PF = 0x40
RTC_UF = 0x10
RTF_ADDRCLASSMASK = 0xf8000000
@@ -2532,6 +2551,8 @@ const (
SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1
SO_VM_SOCKETS_BUFFER_SIZE = 0x0
SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW = 0x8
+ SO_VM_SOCKETS_CONNECT_TIMEOUT_OLD = 0x6
SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7
SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3
SO_VM_SOCKETS_TRUSTED = 0x5
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
index 3ca40ca7f..234fd4a5d 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go
@@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x4004700e
RTC_IRQP_READ = 0x8004700b
RTC_IRQP_SET = 0x4004700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x801c7011
@@ -327,6 +329,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
index ead332091..58619b758 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go
@@ -251,6 +251,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@@ -328,6 +330,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
index 39bdc9455..3a64ff59d 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go
@@ -257,6 +257,8 @@ const (
RTC_EPOCH_SET = 0x4004700e
RTC_IRQP_READ = 0x8004700b
RTC_IRQP_SET = 0x4004700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x801c7011
@@ -334,6 +336,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
index 9aec987db..abe0b9257 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
@@ -247,6 +247,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@@ -324,6 +326,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
index a8bba9491..14d7a8439 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go
@@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@@ -327,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
index ee9e7e202..99e7c4ac0 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go
@@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@@ -327,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
index ba4b288a3..496364c33 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go
@@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@@ -327,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
index bc93afc36..3e4083085 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go
@@ -250,6 +250,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@@ -327,6 +329,7 @@ const (
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
index 9295e6947..1151a7dfa 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go
@@ -305,6 +305,8 @@ const (
RTC_EPOCH_SET = 0x8004700e
RTC_IRQP_READ = 0x4004700b
RTC_IRQP_SET = 0x8004700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x401c7011
@@ -382,6 +384,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
index 1fa081c9a..ed17f249e 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go
@@ -309,6 +309,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@@ -386,6 +388,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
index 74b321149..d84a37c1a 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go
@@ -309,6 +309,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@@ -386,6 +388,7 @@ const (
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
index c91c8ac5b..5cafba83f 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go
@@ -238,6 +238,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@@ -315,6 +317,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
index b66bf2228..6d122da41 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go
@@ -313,6 +313,8 @@ const (
RTC_EPOCH_SET = 0x4008700e
RTC_IRQP_READ = 0x8008700b
RTC_IRQP_SET = 0x4008700c
+ RTC_PARAM_GET = 0x40187013
+ RTC_PARAM_SET = 0x40187014
RTC_PIE_OFF = 0x7006
RTC_PIE_ON = 0x7005
RTC_PLL_GET = 0x80207011
@@ -390,6 +392,7 @@ const (
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
+ SO_RESERVE_MEM = 0x49
SO_REUSEADDR = 0x2
SO_REUSEPORT = 0xf
SO_RXQ_OVFL = 0x28
diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
index f7fb149b0..6bd19e51d 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go
@@ -304,6 +304,8 @@ const (
RTC_EPOCH_SET = 0x8008700e
RTC_IRQP_READ = 0x4008700b
RTC_IRQP_SET = 0x8008700c
+ RTC_PARAM_GET = 0x80187013
+ RTC_PARAM_SET = 0x80187014
RTC_PIE_OFF = 0x20007006
RTC_PIE_ON = 0x20007005
RTC_PLL_GET = 0x40207011
@@ -381,6 +383,7 @@ const (
SO_RCVTIMEO = 0x2000
SO_RCVTIMEO_NEW = 0x44
SO_RCVTIMEO_OLD = 0x2000
+ SO_RESERVE_MEM = 0x52
SO_REUSEADDR = 0x4
SO_REUSEPORT = 0x200
SO_RXQ_OVFL = 0x24
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
index 31847d230..cac1f758b 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go
@@ -445,4 +445,5 @@ const (
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
index 3503cbbde..f327e4a0b 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go
@@ -367,4 +367,5 @@ const (
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
index 5ecd24bf6..fb06a08d4 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go
@@ -409,4 +409,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
index 7e5c94cc7..58285646e 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go
@@ -312,4 +312,5 @@ const (
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
index e1e2a2bf5..3b0418e68 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go
@@ -429,4 +429,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 4445
SYS_LANDLOCK_RESTRICT_SELF = 4446
SYS_PROCESS_MRELEASE = 4448
+ SYS_FUTEX_WAITV = 4449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
index 7651915a3..314ebf166 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go
@@ -359,4 +359,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 5445
SYS_LANDLOCK_RESTRICT_SELF = 5446
SYS_PROCESS_MRELEASE = 5448
+ SYS_FUTEX_WAITV = 5449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
index a26a2c050..b8fbb937a 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go
@@ -359,4 +359,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 5445
SYS_LANDLOCK_RESTRICT_SELF = 5446
SYS_PROCESS_MRELEASE = 5448
+ SYS_FUTEX_WAITV = 5449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
index fda9a6a99..ee309b2ba 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go
@@ -429,4 +429,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 4445
SYS_LANDLOCK_RESTRICT_SELF = 4446
SYS_PROCESS_MRELEASE = 4448
+ SYS_FUTEX_WAITV = 4449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
index e8496150d..ac3748104 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go
@@ -436,4 +436,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
index 5ee0678a3..5aa472111 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go
@@ -408,4 +408,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
index 29c0f9a39..0793ac1a6 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go
@@ -408,4 +408,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
index 5c9a9a3b6..a520962e3 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go
@@ -310,4 +310,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
index 913f50f98..d1738586b 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
@@ -373,4 +373,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
index 0de03a722..dfd5660f9 100644
--- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
+++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go
@@ -387,4 +387,5 @@ const (
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
SYS_PROCESS_MRELEASE = 448
+ SYS_FUTEX_WAITV = 449
)
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go
index e76b7f6f9..66788f156 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -1144,7 +1144,8 @@ const (
PERF_RECORD_BPF_EVENT = 0x12
PERF_RECORD_CGROUP = 0x13
PERF_RECORD_TEXT_POKE = 0x14
- PERF_RECORD_MAX = 0x15
+ PERF_RECORD_AUX_OUTPUT_HW_ID = 0x15
+ PERF_RECORD_MAX = 0x16
PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0
PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1
PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2
@@ -1784,7 +1785,8 @@ const (
const (
NF_NETDEV_INGRESS = 0x0
- NF_NETDEV_NUMHOOKS = 0x1
+ NF_NETDEV_EGRESS = 0x1
+ NF_NETDEV_NUMHOOKS = 0x2
)
const (
@@ -3166,7 +3168,13 @@ const (
DEVLINK_ATTR_RELOAD_ACTION_INFO = 0xa2
DEVLINK_ATTR_RELOAD_ACTION_STATS = 0xa3
DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 0xa4
- DEVLINK_ATTR_MAX = 0xa9
+ DEVLINK_ATTR_RATE_TYPE = 0xa5
+ DEVLINK_ATTR_RATE_TX_SHARE = 0xa6
+ DEVLINK_ATTR_RATE_TX_MAX = 0xa7
+ DEVLINK_ATTR_RATE_NODE_NAME = 0xa8
+ DEVLINK_ATTR_RATE_PARENT_NODE_NAME = 0xa9
+ DEVLINK_ATTR_REGION_MAX_SNAPSHOTS = 0xaa
+ DEVLINK_ATTR_MAX = 0xaa
DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0
DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1
DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0
@@ -3463,7 +3471,14 @@ const (
ETHTOOL_MSG_CABLE_TEST_ACT = 0x1a
ETHTOOL_MSG_CABLE_TEST_TDR_ACT = 0x1b
ETHTOOL_MSG_TUNNEL_INFO_GET = 0x1c
- ETHTOOL_MSG_USER_MAX = 0x21
+ ETHTOOL_MSG_FEC_GET = 0x1d
+ ETHTOOL_MSG_FEC_SET = 0x1e
+ ETHTOOL_MSG_MODULE_EEPROM_GET = 0x1f
+ ETHTOOL_MSG_STATS_GET = 0x20
+ ETHTOOL_MSG_PHC_VCLOCKS_GET = 0x21
+ ETHTOOL_MSG_MODULE_GET = 0x22
+ ETHTOOL_MSG_MODULE_SET = 0x23
+ ETHTOOL_MSG_USER_MAX = 0x23
ETHTOOL_MSG_KERNEL_NONE = 0x0
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
@@ -3494,7 +3509,14 @@ const (
ETHTOOL_MSG_CABLE_TEST_NTF = 0x1b
ETHTOOL_MSG_CABLE_TEST_TDR_NTF = 0x1c
ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY = 0x1d
- ETHTOOL_MSG_KERNEL_MAX = 0x22
+ ETHTOOL_MSG_FEC_GET_REPLY = 0x1e
+ ETHTOOL_MSG_FEC_NTF = 0x1f
+ ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY = 0x20
+ ETHTOOL_MSG_STATS_GET_REPLY = 0x21
+ ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY = 0x22
+ ETHTOOL_MSG_MODULE_GET_REPLY = 0x23
+ ETHTOOL_MSG_MODULE_NTF = 0x24
+ ETHTOOL_MSG_KERNEL_MAX = 0x24
ETHTOOL_A_HEADER_UNSPEC = 0x0
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
ETHTOOL_A_HEADER_DEV_NAME = 0x2
@@ -4009,3 +4031,37 @@ const (
WGALLOWEDIP_A_IPADDR = 0x2
WGALLOWEDIP_A_CIDR_MASK = 0x3
)
+
+const (
+ NL_ATTR_TYPE_INVALID = 0x0
+ NL_ATTR_TYPE_FLAG = 0x1
+ NL_ATTR_TYPE_U8 = 0x2
+ NL_ATTR_TYPE_U16 = 0x3
+ NL_ATTR_TYPE_U32 = 0x4
+ NL_ATTR_TYPE_U64 = 0x5
+ NL_ATTR_TYPE_S8 = 0x6
+ NL_ATTR_TYPE_S16 = 0x7
+ NL_ATTR_TYPE_S32 = 0x8
+ NL_ATTR_TYPE_S64 = 0x9
+ NL_ATTR_TYPE_BINARY = 0xa
+ NL_ATTR_TYPE_STRING = 0xb
+ NL_ATTR_TYPE_NUL_STRING = 0xc
+ NL_ATTR_TYPE_NESTED = 0xd
+ NL_ATTR_TYPE_NESTED_ARRAY = 0xe
+ NL_ATTR_TYPE_BITFIELD32 = 0xf
+
+ NL_POLICY_TYPE_ATTR_UNSPEC = 0x0
+ NL_POLICY_TYPE_ATTR_TYPE = 0x1
+ NL_POLICY_TYPE_ATTR_MIN_VALUE_S = 0x2
+ NL_POLICY_TYPE_ATTR_MAX_VALUE_S = 0x3
+ NL_POLICY_TYPE_ATTR_MIN_VALUE_U = 0x4
+ NL_POLICY_TYPE_ATTR_MAX_VALUE_U = 0x5
+ NL_POLICY_TYPE_ATTR_MIN_LENGTH = 0x6
+ NL_POLICY_TYPE_ATTR_MAX_LENGTH = 0x7
+ NL_POLICY_TYPE_ATTR_POLICY_IDX = 0x8
+ NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE = 0x9
+ NL_POLICY_TYPE_ATTR_BITFIELD32_MASK = 0xa
+ NL_POLICY_TYPE_ATTR_PAD = 0xb
+ NL_POLICY_TYPE_ATTR_MASK = 0xc
+ NL_POLICY_TYPE_ATTR_MAX = 0xc
+)
diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go
index 200b62a00..cf44e6933 100644
--- a/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -363,6 +363,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error)
//sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
//sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error)
+//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32)
+//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32)
// Volume Management Functions
//sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 655447e8f..e19471c6a 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -2749,6 +2749,43 @@ type PROCESS_BASIC_INFORMATION struct {
InheritedFromUniqueProcessId uintptr
}
+type SYSTEM_PROCESS_INFORMATION struct {
+ NextEntryOffset uint32
+ NumberOfThreads uint32
+ WorkingSetPrivateSize int64
+ HardFaultCount uint32
+ NumberOfThreadsHighWatermark uint32
+ CycleTime uint64
+ CreateTime int64
+ UserTime int64
+ KernelTime int64
+ ImageName NTUnicodeString
+ BasePriority int32
+ UniqueProcessID uintptr
+ InheritedFromUniqueProcessID uintptr
+ HandleCount uint32
+ SessionID uint32
+ UniqueProcessKey *uint32
+ PeakVirtualSize uintptr
+ VirtualSize uintptr
+ PageFaultCount uint32
+ PeakWorkingSetSize uintptr
+ WorkingSetSize uintptr
+ QuotaPeakPagedPoolUsage uintptr
+ QuotaPagedPoolUsage uintptr
+ QuotaPeakNonPagedPoolUsage uintptr
+ QuotaNonPagedPoolUsage uintptr
+ PagefileUsage uintptr
+ PeakPagefileUsage uintptr
+ PrivatePageCount uintptr
+ ReadOperationCount int64
+ WriteOperationCount int64
+ OtherOperationCount int64
+ ReadTransferCount int64
+ WriteTransferCount int64
+ OtherTransferCount int64
+}
+
// SystemInformationClasses for NtQuerySystemInformation and NtSetSystemInformation
const (
SystemBasicInformation = iota
@@ -3135,3 +3172,5 @@ type ModuleInfo struct {
SizeOfImage uint32
EntryPoint uintptr
}
+
+const ALL_PROCESSOR_GROUPS = 0xFFFF
diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 1055d47ed..9ea1a44f0 100644
--- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -226,6 +226,7 @@ var (
procFreeLibrary = modkernel32.NewProc("FreeLibrary")
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
procGetACP = modkernel32.NewProc("GetACP")
+ procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts")
procGetCommandLineW = modkernel32.NewProc("GetCommandLineW")
procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
@@ -251,6 +252,7 @@ var (
procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW")
procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives")
procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW")
+ procGetMaximumProcessorCount = modkernel32.NewProc("GetMaximumProcessorCount")
procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW")
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
@@ -1967,6 +1969,12 @@ func GetACP() (acp uint32) {
return
}
+func GetActiveProcessorCount(groupNumber uint16) (ret uint32) {
+ r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0)
+ ret = uint32(r0)
+ return
+}
+
func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
if r1 == 0 {
@@ -2169,6 +2177,12 @@ func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err er
return
}
+func GetMaximumProcessorCount(groupNumber uint16) (ret uint32) {
+ r0, _, _ := syscall.Syscall(procGetMaximumProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0)
+ ret = uint32(r0)
+ return
+}
+
func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) {
r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size))
n = uint32(r0)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index c618886bc..1a2af971c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -11,7 +11,7 @@ github.com/Microsoft/go-winio/backuptar
github.com/Microsoft/go-winio/pkg/guid
github.com/Microsoft/go-winio/pkg/security
github.com/Microsoft/go-winio/vhd
-# github.com/Microsoft/hcsshim v0.9.1
+# github.com/Microsoft/hcsshim v0.9.2
github.com/Microsoft/hcsshim
github.com/Microsoft/hcsshim/computestorage
github.com/Microsoft/hcsshim/internal/cow
@@ -41,7 +41,7 @@ github.com/beorn7/perks/quantile
# github.com/blang/semver v3.5.1+incompatible
## explicit
github.com/blang/semver
-# github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
+# github.com/buger/goterm v1.0.1
## explicit
github.com/buger/goterm
# github.com/cespare/xxhash/v2 v2.1.2
@@ -69,7 +69,7 @@ github.com/containerd/containerd/log
github.com/containerd/containerd/pkg/userns
github.com/containerd/containerd/platforms
github.com/containerd/containerd/sys
-# github.com/containerd/stargz-snapshotter/estargz v0.10.1
+# github.com/containerd/stargz-snapshotter/estargz v0.11.0
github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil
# github.com/containernetworking/cni v1.0.1
@@ -87,7 +87,7 @@ github.com/containernetworking/cni/pkg/version
# github.com/containernetworking/plugins v1.0.1
## explicit
github.com/containernetworking/plugins/pkg/ns
-# github.com/containers/buildah v1.23.1-0.20220112160421-d744ebc4b1d5
+# github.com/containers/buildah v1.24.1
## explicit
github.com/containers/buildah
github.com/containers/buildah/bind
@@ -109,7 +109,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
-# github.com/containers/common v0.46.1-0.20220117145719-da777f8b15b1
+# github.com/containers/common v0.47.3
## explicit
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
@@ -153,7 +153,7 @@ github.com/containers/common/version
# github.com/containers/conmon v2.0.20+incompatible
## explicit
github.com/containers/conmon/runner/config
-# github.com/containers/image/v5 v5.18.0
+# github.com/containers/image/v5 v5.19.1
## explicit
github.com/containers/image/v5/copy
github.com/containers/image/v5/directory
@@ -194,6 +194,7 @@ github.com/containers/image/v5/pkg/shortnames
github.com/containers/image/v5/pkg/strslice
github.com/containers/image/v5/pkg/sysregistriesv2
github.com/containers/image/v5/pkg/tlsclientconfig
+github.com/containers/image/v5/sif
github.com/containers/image/v5/signature
github.com/containers/image/v5/storage
github.com/containers/image/v5/tarball
@@ -221,7 +222,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils
github.com/containers/ocicrypt/utils/keyprovider
-# github.com/containers/psgo v1.7.1
+# github.com/containers/psgo v1.7.2
## explicit
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
@@ -230,7 +231,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.37.1-0.20211213220314-73a749e4fec5
+# github.com/containers/storage v1.38.2
## explicit
github.com/containers/storage
github.com/containers/storage/drivers
@@ -303,7 +304,7 @@ github.com/digitalocean/go-libvirt
github.com/digitalocean/go-libvirt/internal/constants
github.com/digitalocean/go-libvirt/internal/event
github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2
-# github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f
+# github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
## explicit
github.com/digitalocean/go-qemu/qmp
# github.com/disiqueira/gotree/v3 v3.0.2
@@ -341,6 +342,7 @@ github.com/docker/docker/api/types/versions
github.com/docker/docker/api/types/volume
github.com/docker/docker/client
github.com/docker/docker/errdefs
+github.com/docker/docker/opts
github.com/docker/docker/pkg/archive
github.com/docker/docker/pkg/fileutils
github.com/docker/docker/pkg/homedir
@@ -356,14 +358,14 @@ github.com/docker/docker/pkg/system
# github.com/docker/docker-credential-helpers v0.6.4
github.com/docker/docker-credential-helpers/client
github.com/docker/docker-credential-helpers/credentials
-# github.com/docker/go-connections v0.4.0
+# github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
## explicit
github.com/docker/go-connections/nat
github.com/docker/go-connections/sockets
github.com/docker/go-connections/tlsconfig
# github.com/docker/go-metrics v0.0.1
github.com/docker/go-metrics
-# github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc
+# github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
## explicit
github.com/docker/go-plugins-helpers/sdk
github.com/docker/go-plugins-helpers/volume
@@ -371,12 +373,15 @@ github.com/docker/go-plugins-helpers/volume
## explicit
github.com/docker/go-units
# github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316
+github.com/docker/libnetwork/ipamutils
github.com/docker/libnetwork/resolvconf
github.com/docker/libnetwork/resolvconf/dns
github.com/docker/libnetwork/types
# github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
## explicit
github.com/dtylman/scp
+# github.com/felixge/httpsnoop v1.0.1
+github.com/felixge/httpsnoop
# github.com/fsnotify/fsnotify v1.5.1
## explicit
github.com/fsnotify/fsnotify
@@ -415,13 +420,13 @@ github.com/google/go-cmp/cmp/internal/value
github.com/google/go-intervals/intervalset
# github.com/google/gofuzz v1.1.0
github.com/google/gofuzz
-# github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
+# github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
## explicit
github.com/google/shlex
# github.com/google/uuid v1.3.0
## explicit
github.com/google/uuid
-# github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33
+# github.com/gorilla/handlers v1.5.1
## explicit
github.com/gorilla/handlers
# github.com/gorilla/mux v1.8.0
@@ -448,12 +453,12 @@ github.com/imdario/mergo
github.com/inconshreveable/mousetrap
# github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee
github.com/ishidawataru/sctp
-# github.com/jinzhu/copier v0.3.4
+# github.com/jinzhu/copier v0.3.5
github.com/jinzhu/copier
# github.com/json-iterator/go v1.1.12
## explicit
github.com/json-iterator/go
-# github.com/klauspost/compress v1.13.6
+# github.com/klauspost/compress v1.14.2
github.com/klauspost/compress
github.com/klauspost/compress/flate
github.com/klauspost/compress/fse
@@ -499,8 +504,6 @@ github.com/morikuni/aec
# github.com/mrunalp/fileutils v0.5.0
## explicit
github.com/mrunalp/fileutils
-# github.com/mtrmac/gpgme v0.1.2
-github.com/mtrmac/gpgme
# github.com/nxadm/tail v1.4.8
github.com/nxadm/tail
github.com/nxadm/tail/ratelimiter
@@ -538,7 +541,7 @@ github.com/onsi/ginkgo/reporters/stenographer
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
github.com/onsi/ginkgo/types
-# github.com/onsi/gomega v1.17.0 => github.com/onsi/gomega v1.16.0
+# github.com/onsi/gomega v1.18.1 => github.com/onsi/gomega v1.16.0
## explicit
github.com/onsi/gomega
github.com/onsi/gomega/format
@@ -556,7 +559,7 @@ github.com/onsi/gomega/types
# github.com/opencontainers/go-digest v1.0.0
## explicit
github.com/opencontainers/go-digest
-# github.com/opencontainers/image-spec v1.0.3-0.20211215212317-ea0209f50ae1
+# github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198
## explicit
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
@@ -569,10 +572,10 @@ github.com/opencontainers/runc/libcontainer/devices
github.com/opencontainers/runc/libcontainer/user
github.com/opencontainers/runc/libcontainer/userns
github.com/opencontainers/runc/libcontainer/utils
-# github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
+# github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab
## explicit
github.com/opencontainers/runtime-spec/specs-go
-# github.com/opencontainers/runtime-tools v0.9.1-0.20211020193359-09d837bf40a7
+# github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f
## explicit
github.com/opencontainers/runtime-tools/error
github.com/opencontainers/runtime-tools/filepath
@@ -586,7 +589,7 @@ github.com/opencontainers/selinux/go-selinux
github.com/opencontainers/selinux/go-selinux/label
github.com/opencontainers/selinux/pkg/pwalk
github.com/opencontainers/selinux/pkg/pwalkdir
-# github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656
+# github.com/openshift/imagebuilder v1.2.2
github.com/openshift/imagebuilder
github.com/openshift/imagebuilder/dockerfile/command
github.com/openshift/imagebuilder/dockerfile/parser
@@ -601,6 +604,8 @@ github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
+# github.com/proglottis/gpgme v0.1.1
+github.com/proglottis/gpgme
# github.com/prometheus/client_golang v1.7.1
github.com/prometheus/client_golang/prometheus
github.com/prometheus/client_golang/prometheus/internal
@@ -649,6 +654,8 @@ github.com/stefanberger/go-pkcs11uri
## explicit
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
+# github.com/sylabs/sif/v2 v2.3.1
+github.com/sylabs/sif/v2/pkg/sif
# github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
## explicit
github.com/syndtr/gocapability/capability
@@ -678,12 +685,12 @@ github.com/vbauerster/mpb/v6
github.com/vbauerster/mpb/v6/cwriter
github.com/vbauerster/mpb/v6/decor
github.com/vbauerster/mpb/v6/internal
-# github.com/vbauerster/mpb/v7 v7.3.0
+# github.com/vbauerster/mpb/v7 v7.3.2
github.com/vbauerster/mpb/v7
github.com/vbauerster/mpb/v7/cwriter
github.com/vbauerster/mpb/v7/decor
github.com/vbauerster/mpb/v7/internal
-# github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
+# github.com/vishvananda/netlink v1.1.1-0.20220115184804-dd687eb2f2d4
## explicit
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl
@@ -706,7 +713,7 @@ go.opencensus.io/internal
go.opencensus.io/trace
go.opencensus.io/trace/internal
go.opencensus.io/trace/tracestate
-# golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
+# golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
## explicit
golang.org/x/crypto/blowfish
golang.org/x/crypto/cast5
@@ -729,7 +736,7 @@ golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/knownhosts
golang.org/x/crypto/ssh/terminal
-# golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
+# golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d
golang.org/x/net/context
golang.org/x/net/html
golang.org/x/net/html/atom
@@ -738,15 +745,13 @@ golang.org/x/net/http/httpguts
golang.org/x/net/http2
golang.org/x/net/http2/hpack
golang.org/x/net/idna
-golang.org/x/net/internal/socks
golang.org/x/net/internal/timeseries
-golang.org/x/net/proxy
golang.org/x/net/trace
# golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
## explicit
golang.org/x/sync/errgroup
golang.org/x/sync/semaphore
-# golang.org/x/sys v0.0.0-20211214234402-4825e8c3871d
+# golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
## explicit
golang.org/x/sys/cpu
golang.org/x/sys/execabs