summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml38
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md36
-rw-r--r--.gitignore1
-rw-r--r--Makefile152
-rw-r--r--RELEASE_PROCESS.md18
-rw-r--r--cmd/podman/common/completion.go12
-rw-r--r--cmd/podman/common/create.go29
-rw-r--r--cmd/podman/common/create_test.go53
-rw-r--r--cmd/podman/containers/cleanup.go8
-rw-r--r--cmd/podman/containers/create.go17
-rw-r--r--cmd/podman/containers/ps.go12
-rw-r--r--cmd/podman/containers/run.go8
-rw-r--r--cmd/podman/generate/generate.go2
-rw-r--r--cmd/podman/images/build.go14
-rw-r--r--cmd/podman/images/inspect.go6
-rw-r--r--cmd/podman/images/prune.go5
-rw-r--r--cmd/podman/images/save.go2
-rw-r--r--cmd/podman/images/utils_linux.go4
-rw-r--r--cmd/podman/inspect/inspect.go2
-rw-r--r--cmd/podman/machine/init.go29
-rw-r--r--cmd/podman/machine/list.go81
-rw-r--r--cmd/podman/machine/ssh.go29
-rw-r--r--cmd/podman/networks/inspect.go2
-rw-r--r--cmd/podman/play/play.go2
-rw-r--r--cmd/podman/pods/create.go32
-rw-r--r--cmd/podman/registry/config.go7
-rw-r--r--cmd/podman/root.go11
-rw-r--r--cmd/podman/system/prune.go6
-rw-r--r--cmd/podman/system/service.go7
-rwxr-xr-xcontrib/cirrus/runner.sh39
-rwxr-xr-xcontrib/cirrus/setup_environment.sh38
-rw-r--r--contrib/msi/podman.wxs8
-rw-r--r--contrib/podmanimage/README.md4
-rwxr-xr-xdocs/dckrman.sh1
-rw-r--r--docs/source/markdown/links/podman-container-inspect.11
-rw-r--r--docs/source/markdown/links/podman-image-inspect.11
-rw-r--r--docs/source/markdown/podman-build.1.md52
-rw-r--r--docs/source/markdown/podman-container-inspect.1.md318
-rw-r--r--docs/source/markdown/podman-container.1.md2
-rw-r--r--docs/source/markdown/podman-create.1.md17
-rw-r--r--docs/source/markdown/podman-generate-kube.1.md8
-rw-r--r--docs/source/markdown/podman-image-inspect.1.md105
-rw-r--r--docs/source/markdown/podman-image-prune.1.md4
-rw-r--r--docs/source/markdown/podman-image.1.md48
-rw-r--r--docs/source/markdown/podman-inspect.1.md4
-rw-r--r--docs/source/markdown/podman-machine-init.1.md6
-rw-r--r--docs/source/markdown/podman-machine-ssh.1.md6
-rw-r--r--docs/source/markdown/podman-network-connect.1.md2
-rw-r--r--docs/source/markdown/podman-pod-create.1.md18
-rw-r--r--docs/source/markdown/podman-pod-inspect.1.md2
-rw-r--r--docs/source/markdown/podman-rmi.1.md4
-rw-r--r--docs/source/markdown/podman-run.1.md19
-rw-r--r--docs/source/markdown/podman-save.1.md4
-rw-r--r--docs/source/markdown/podman-system-service.1.md5
-rw-r--r--docs/source/markdown/podman-volume-inspect.1.md2
-rw-r--r--go.mod20
-rw-r--r--go.sum54
-rwxr-xr-xhack/get_release_info.sh70
-rw-r--r--hack/podman-registry-go/registry.go2
-rw-r--r--libpod/boltdb_state.go23
-rw-r--r--libpod/boltdb_state_internal.go4
-rw-r--r--libpod/boltdb_state_linux.go2
-rw-r--r--libpod/boltdb_state_unsupported.go13
-rw-r--r--libpod/container.go28
-rw-r--r--libpod/container_api.go6
-rw-r--r--libpod/container_commit.go2
-rw-r--r--libpod/container_config.go2
-rw-r--r--libpod/container_copy_linux.go2
-rw-r--r--libpod/container_copy_unsupported.go16
-rw-r--r--libpod/container_exec.go28
-rw-r--r--libpod/container_inspect.go59
-rw-r--r--libpod/container_internal.go69
-rw-r--r--libpod/container_internal_linux.go133
-rw-r--r--libpod/container_internal_unsupported.go64
-rw-r--r--libpod/container_log.go14
-rw-r--r--libpod/container_path_resolution.go8
-rw-r--r--libpod/container_stat_unsupported.go13
-rw-r--r--libpod/container_top_unsupported.go23
-rw-r--r--libpod/container_unsupported.go5
-rw-r--r--libpod/define/config.go6
-rw-r--r--libpod/define/container_inspect.go8
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/events.go14
-rw-r--r--libpod/events/journal_linux.go2
-rw-r--r--libpod/healthcheck.go16
-rw-r--r--libpod/healthcheck_unsupported.go21
-rw-r--r--libpod/info.go2
-rw-r--r--libpod/kube.go85
-rw-r--r--libpod/lock/file/file_lock.go2
-rw-r--r--libpod/lock/shm/shm_lock_nocgo.go20
-rw-r--r--libpod/logs/log.go2
-rw-r--r--libpod/network/cni/cni_conversion.go8
-rw-r--r--libpod/network/cni/cni_exec.go12
-rw-r--r--libpod/network/cni/config.go8
-rw-r--r--libpod/network/cni/config_test.go21
-rw-r--r--libpod/network/cni/network.go2
-rw-r--r--libpod/network/cni/run.go22
-rw-r--r--libpod/network/cni/run_test.go45
-rw-r--r--libpod/network/types/network.go32
-rw-r--r--libpod/networking_linux.go65
-rw-r--r--libpod/networking_slirp4netns.go12
-rw-r--r--libpod/networking_unsupported.go40
-rw-r--r--libpod/oci_attach_linux.go45
-rw-r--r--libpod/oci_attach_unsupported.go17
-rw-r--r--libpod/oci_conmon_exec_linux.go4
-rw-r--r--libpod/oci_conmon_linux.go34
-rw-r--r--libpod/oci_conmon_unsupported.go132
-rw-r--r--libpod/oci_util.go6
-rw-r--r--libpod/options.go14
-rw-r--r--libpod/pod.go6
-rw-r--r--libpod/pod_api.go56
-rw-r--r--libpod/pod_internal.go2
-rw-r--r--libpod/pod_top_unsupported.go10
-rw-r--r--libpod/reset.go10
-rw-r--r--libpod/runtime.go45
-rw-r--r--libpod/runtime_cstorage.go8
-rw-r--r--libpod/runtime_ctr.go49
-rw-r--r--libpod/runtime_img.go23
-rw-r--r--libpod/runtime_migrate.go4
-rw-r--r--libpod/runtime_migrate_unsupported.go15
-rw-r--r--libpod/runtime_pod_linux.go20
-rw-r--r--libpod/runtime_pod_unsupported.go18
-rw-r--r--libpod/runtime_volume_linux.go10
-rw-r--r--libpod/runtime_volume_unsupported.go21
-rw-r--r--libpod/shutdown/handler.go2
-rw-r--r--libpod/stats_unsupported.go10
-rw-r--r--libpod/storage.go30
-rw-r--r--libpod/util.go8
-rw-r--r--libpod/util_linux.go2
-rw-r--r--libpod/util_unsupported.go34
-rw-r--r--libpod/volume_internal_unsupported.go15
-rw-r--r--pkg/api/handlers/compat/containers.go6
-rw-r--r--pkg/api/handlers/compat/containers_start.go2
-rw-r--r--pkg/api/handlers/compat/containers_stats.go4
-rw-r--r--pkg/api/handlers/compat/events.go2
-rw-r--r--pkg/api/handlers/libpod/images.go25
-rw-r--r--pkg/api/handlers/libpod/pods.go8
-rw-r--r--pkg/api/handlers/types.go3
-rw-r--r--pkg/api/handlers/utils/containers.go4
-rw-r--r--pkg/api/handlers/utils/handler.go8
-rw-r--r--pkg/api/server/register_images.go27
-rw-r--r--pkg/api/server/server.go4
-rw-r--r--pkg/auth/auth.go2
-rw-r--r--pkg/autoupdate/autoupdate.go3
-rw-r--r--pkg/bindings/connection.go4
-rw-r--r--pkg/bindings/containers/attach.go14
-rw-r--r--pkg/bindings/images/build.go11
-rw-r--r--pkg/bindings/images/types.go4
-rw-r--r--pkg/bindings/images/types_export_options.go15
-rw-r--r--pkg/bindings/images/types_prune_options.go15
-rw-r--r--pkg/checkpoint/checkpoint_restore.go2
-rw-r--r--pkg/domain/entities/images.go9
-rw-r--r--pkg/domain/entities/pods.go67
-rw-r--r--pkg/domain/infra/abi/containers.go65
-rw-r--r--pkg/domain/infra/abi/containers_runlabel.go4
-rw-r--r--pkg/domain/infra/abi/generate.go12
-rw-r--r--pkg/domain/infra/abi/images.go20
-rw-r--r--pkg/domain/infra/abi/manifest.go2
-rw-r--r--pkg/domain/infra/abi/play.go13
-rw-r--r--pkg/domain/infra/abi/secrets.go2
-rw-r--r--pkg/domain/infra/abi/terminal/sigproxy_linux.go4
-rw-r--r--pkg/domain/infra/abi/terminal/terminal_linux.go4
-rw-r--r--pkg/domain/infra/abi/trust.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go2
-rw-r--r--pkg/domain/infra/tunnel/containers.go6
-rw-r--r--pkg/domain/infra/tunnel/images.go6
-rw-r--r--pkg/env/env.go5
-rw-r--r--pkg/errorhandling/errorhandling.go4
-rw-r--r--pkg/hooks/exec/exec.go2
-rw-r--r--pkg/hooks/exec/runtimeconfigfilter.go2
-rw-r--r--pkg/hooks/monitor.go4
-rw-r--r--pkg/machine/config.go3
-rw-r--r--pkg/machine/fcos.go2
-rw-r--r--pkg/machine/ignition.go88
-rw-r--r--pkg/machine/qemu/config.go2
-rw-r--r--pkg/machine/qemu/machine.go15
-rw-r--r--pkg/netns/netns_linux.go8
-rw-r--r--pkg/ps/ps.go15
-rw-r--r--pkg/rootless/rootless_linux.c1
-rw-r--r--pkg/rootless/rootless_linux.go16
-rw-r--r--pkg/rootlessport/rootlessport_linux.go32
-rw-r--r--pkg/servicereaper/service.go2
-rw-r--r--pkg/specgen/generate/config_linux.go1
-rw-r--r--pkg/specgen/generate/container.go2
-rw-r--r--pkg/specgen/generate/container_create.go31
-rw-r--r--pkg/specgen/generate/kube/kube.go13
-rw-r--r--pkg/specgen/generate/oci.go11
-rw-r--r--pkg/specgen/generate/security.go2
-rw-r--r--pkg/specgen/generate/validate.go3
-rw-r--r--pkg/specgen/podspecgen.go2
-rw-r--r--pkg/specgen/specgen.go4
-rw-r--r--pkg/specgenutil/volumes.go63
-rw-r--r--pkg/trust/trust.go4
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py2
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_image.py5
-rwxr-xr-xtest/compose/test-compose1
-rw-r--r--test/e2e/commit_test.go2
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/config/containers.conf1
-rw-r--r--test/e2e/container_inspect_test.go8
-rw-r--r--test/e2e/containers_conf_test.go8
-rw-r--r--test/e2e/create_test.go2
-rw-r--r--test/e2e/generate_kube_test.go50
-rw-r--r--test/e2e/healthcheck_run_test.go33
-rw-r--r--test/e2e/inspect_test.go4
-rw-r--r--test/e2e/network_connect_disconnect_test.go18
-rw-r--r--test/e2e/network_test.go52
-rw-r--r--test/e2e/play_build_test.go19
-rw-r--r--test/e2e/play_kube_test.go57
-rw-r--r--test/e2e/pod_create_test.go27
-rw-r--r--test/e2e/pod_inspect_test.go4
-rw-r--r--test/e2e/pod_start_test.go4
-rw-r--r--test/e2e/ps_test.go61
-rw-r--r--test/e2e/rename_test.go25
-rw-r--r--test/e2e/run_networking_test.go136
-rw-r--r--test/e2e/run_test.go4
-rw-r--r--test/e2e/run_volume_test.go94
-rw-r--r--test/e2e/stop_test.go11
-rw-r--r--test/e2e/system_connection_test.go4
-rw-r--r--test/e2e/top_test.go6
-rw-r--r--test/system/001-basic.bats3
-rw-r--r--test/system/035-logs.bats31
-rw-r--r--test/system/040-ps.bats32
-rw-r--r--test/system/060-mount.bats2
-rw-r--r--test/system/065-cp.bats43
-rw-r--r--test/system/070-build.bats39
-rw-r--r--test/system/080-pause.bats2
-rw-r--r--test/system/120-load.bats16
-rw-r--r--test/system/160-volumes.bats9
-rw-r--r--test/system/220-healthcheck.bats5
-rw-r--r--test/system/270-socket-activation.bats24
-rw-r--r--test/system/330-corrupt-images.bats2
-rw-r--r--test/system/410-selinux.bats4
-rw-r--r--test/system/420-cgroups.bats4
-rw-r--r--test/system/500-networking.bats8
-rw-r--r--test/system/600-completion.bats4
-rw-r--r--test/system/700-play.bats17
-rw-r--r--test/system/helpers.bash12
-rw-r--r--test/testvol/main.go2
-rw-r--r--test/utils/utils.go15
-rw-r--r--test/version/main.go11
-rw-r--r--utils/utils.go7
-rw-r--r--utils/utils_supported.go6
-rw-r--r--vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go108
-rw-r--r--vendor/github.com/containernetworking/cni/libcni/api.go74
-rw-r--r--vendor/github.com/containernetworking/cni/libcni/conf.go14
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/exec.go10
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/020/types.go85
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/040/types.go306
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/100/types.go307
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/args.go18
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/create/create.go56
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/current/types.go276
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go92
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/internal/create.go66
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/types.go31
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/conf.go15
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/plugin.go8
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/version.go52
-rw-r--r--vendor/github.com/containers/common/libimage/copier.go20
-rw-r--r--vendor/github.com/containers/common/libimage/filters.go38
-rw-r--r--vendor/github.com/containers/common/libimage/image.go68
-rw-r--r--vendor/github.com/containers/common/libimage/load.go59
-rw-r--r--vendor/github.com/containers/common/libimage/manifests/manifests.go10
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go2
-rw-r--r--vendor/github.com/containers/common/libimage/runtime.go35
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go12
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go23
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf32
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go25
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry.go2
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secrets.go6
-rw-r--r--vendor/github.com/containers/common/pkg/secrets/secretsdb.go12
-rw-r--r--vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go10
-rw-r--r--vendor/github.com/containers/common/pkg/supplemented/supplemented.go4
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go2
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/github.com/containers/psgo/.codespellrc2
-rw-r--r--vendor/github.com/containers/psgo/.golangci.yml6
-rw-r--r--vendor/github.com/containers/psgo/.travis.yml19
-rw-r--r--vendor/github.com/containers/psgo/Makefile40
-rw-r--r--vendor/github.com/containers/psgo/README.md4
-rw-r--r--vendor/github.com/containers/psgo/go.mod3
-rw-r--r--vendor/github.com/containers/psgo/go.sum1
-rw-r--r--vendor/github.com/containers/psgo/internal/host/host.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/ns.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/pids.go31
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go2
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go2
-rw-r--r--vendor/github.com/containers/psgo/psgo.go54
-rw-r--r--vendor/github.com/containers/storage/.cirrus.yml15
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/drivers/aufs/aufs.go6
-rw-r--r--vendor/github.com/containers/storage/drivers/fsdiff.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go91
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/randomid.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/template.go4
-rw-r--r--vendor/github.com/containers/storage/go.mod5
-rw-r--r--vendor/github.com/containers/storage/go.sum12
-rw-r--r--vendor/github.com/containers/storage/layers.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/archive.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/chunked/storage_linux.go86
-rw-r--r--vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go10
-rw-r--r--vendor/github.com/containers/storage/pkg/loopback/loopback.go4
-rw-r--r--vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go30
-rw-r--r--vendor/github.com/containers/storage/store.go4
-rw-r--r--vendor/github.com/containers/storage/types/utils.go2
-rw-r--r--vendor/github.com/containers/storage/userns.go2
-rw-r--r--vendor/github.com/klauspost/compress/LICENSE12
-rw-r--r--vendor/github.com/klauspost/compress/README.md12
-rw-r--r--vendor/github.com/klauspost/compress/flate/fast_encoder.go25
-rw-r--r--vendor/github.com/klauspost/compress/huff0/decompress.go275
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go1
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go2
-rw-r--r--vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s66
-rw-r--r--vendor/github.com/mattn/go-isatty/.travis.yml14
-rw-r--r--vendor/github.com/mattn/go-isatty/go.mod2
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_bsd.go1
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_others.go3
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_plan9.go1
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_solaris.go9
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_tcgets.go3
-rw-r--r--vendor/github.com/mattn/go-isatty/isatty_windows.go6
-rw-r--r--vendor/github.com/mattn/go-isatty/renovate.json8
-rw-r--r--vendor/github.com/mitchellh/mapstructure/CHANGELOG.md10
-rw-r--r--vendor/github.com/mitchellh/mapstructure/decode_hooks.go3
-rw-r--r--vendor/github.com/mitchellh/mapstructure/mapstructure.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/class_linux.go10
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go121
-rw-r--r--vendor/github.com/vishvananda/netlink/filter_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_linux.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_unspecified.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/inet_diag.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/ipset_linux.go60
-rw-r--r--vendor/github.com/vishvananda/netlink/link.go195
-rw-r--r--vendor/github.com/vishvananda/netlink/link_linux.go131
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/devlink_linux.go23
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/link_linux.go36
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/nl_linux.go11
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go (renamed from vendor/github.com/vishvananda/netlink/nl/parse_attr.go)14
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc_linux.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/route.go14
-rw-r--r--vendor/github.com/vishvananda/netlink/route_linux.go218
-rw-r--r--vendor/github.com/vishvananda/netlink/route_unspecified.go10
-rw-r--r--vendor/github.com/vishvananda/netlink/socket_linux.go47
-rw-r--r--vendor/github.com/vishvananda/netlink/tcp.go66
-rw-r--r--vendor/github.com/vishvananda/netlink/tcp_linux.go76
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go23
-rw-r--r--vendor/github.com/vishvananda/netns/README.md11
-rw-r--r--vendor/github.com/vishvananda/netns/netns_linux.go18
-rw-r--r--vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE27
-rw-r--r--vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS22
-rw-r--r--vendor/modules.txt31
361 files changed, 6091 insertions, 2710 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 581aaaa7b..9897a9f7f 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -359,11 +359,15 @@ osx_alt_build_task:
TEST_FLAVOR: "altbuild"
ALT_NAME: 'OSX Cross'
osx_instance:
- image: 'catalina-base'
- script:
+ image: 'big-sur-base'
+ setup_script:
- brew install go
- brew install go-md2man
- - make podman-remote-release-darwin.zip
+ - go version
+ build_amd64_script:
+ - make podman-remote-release-darwin_amd64.zip
+ build_arm64_script:
+ - make podman-remote-release-darwin_arm64.zip GOARCH=arm64
always: *binary_artifacts
@@ -633,6 +637,33 @@ 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
+ # 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.
+ # allow_failures: $CI == $CI
+ depends_on:
+ - rootless_integration_test
+ gce_instance: *standardvm
+ env:
+ <<: *ubuntu_envvars
+ TEST_FLAVOR: 'gitlab'
+ PRIV_NAME: rootless
+ clone_script: *noop # Comes from cache
+ gopath_cache: *ro_gopath_cache
+ setup_script: *setup
+ main_script: *main
+ always:
+ <<: *logs_artifacts
+ junit_artifacts:
+ path: gitlab-runner-podman.xml
+ type: text/xml
+ format: junit
+
upgrade_test_task:
name: "Upgrade test: from $PODMAN_UPGRADE_FROM"
alias: upgrade_test
@@ -716,6 +747,7 @@ success_task:
- local_system_test
- remote_system_test
- rootless_system_test
+ - rootless_gitlab_test
- upgrade_test
- buildah_bud_test
- meta
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 568cf7240..f5f0b21be 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,7 +1,41 @@
<!--
Thanks for sending a pull request!
-Please make sure you've read our contributing guidelines and how to submit a pull request (https://github.com/containers/podman/blob/master/CONTRIBUTING.md#submitting-pull-requests).
+Please make sure you've read our contributing guidelines and how to submit a pull request (https://github.com/containers/podman/blob/main/CONTRIBUTING.md#submitting-pull-requests).
In case you're only changing docs, make sure to prefix the pull-request title with "[CI:DOCS]". That will prevent functional tests from running and save time and energy.
+
+Finally, be sure to sign commits with your real name. Since by opening
+a PR you already have commits, you can add signatures if needed with
+something like `git commit -s --amend`.
-->
+
+#### What this PR does / why we need it:
+
+<!---
+Please put your overall PR description here
+-->
+
+#### How to verify it
+
+<!---
+Please specify the precise conditions and/or the specific test(s) which must pass.
+-->
+
+#### Which issue(s) this PR fixes:
+
+<!--
+Please uncomment this block and include only one of the following on a
+line by itself:
+
+None
+
+-OR-
+
+Fixes #<issue number>
+
+*** Please also put 'Fixes #' in the commit and PR description***
+
+-->
+
+#### Special notes for your reviewer:
diff --git a/.gitignore b/.gitignore
index 08e5309ee..d54013bfd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ release.txt
/test/checkseccomp/checkseccomp
/test/copyimg/copyimg
/test/goecho/goecho
+/test/version/version
/test/testvol/testvol
.vscode*
tags
diff --git a/Makefile b/Makefile
index cf796ed3c..590675d25 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,8 @@
export GOPROXY=https://proxy.golang.org
GO ?= go
+GO_LDFLAGS:= $(shell if $(GO) version|grep -q gccgo ; then echo "-gccgoflags"; else echo "-ldflags"; fi)
+GOCMD = CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) $(GO)
COVERAGE_PATH ?= .coverage
DESTDIR ?=
EPOCH_TEST_COMMIT ?= $(shell git merge-base $${DEST_BRANCH:-main} HEAD)
@@ -107,12 +109,9 @@ LIBSECCOMP_COMMIT := v2.3.3
# caller may override in special circumstances if needed.
GINKGOTIMEOUT ?= -timeout=90m
-RELEASE_VERSION ?= $(shell hack/get_release_info.sh VERSION)
-RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER|sed -e 's/^v\(.*\)/\1/')
-RELEASE_DIST ?= $(shell hack/get_release_info.sh DIST)
-RELEASE_DIST_VER ?= $(shell hack/get_release_info.sh DIST_VER)
-RELEASE_ARCH ?= $(shell hack/get_release_info.sh ARCH)
-RELEASE_BASENAME := $(shell hack/get_release_info.sh BASENAME)
+# Conditional required to produce empty-output if binary not built yet.
+RELEASE_VERSION = $(shell if test -x test/version/version; then test/version/version; fi)
+RELEASE_NUMBER = $(shell echo "$(RELEASE_VERSION)" | sed -e 's/^v\(.*\)/\1/')
# If non-empty, logs all output from server during remote system testing
PODMAN_SERVER_LOG ?=
@@ -153,7 +152,11 @@ err_if_empty = $(if $(strip $($(1))),$(strip $($(1))),$(error Required variable
# Podman does not work w/o CGO_ENABLED, except in some very specific cases
CGO_ENABLED ?= 1
# Default to the native OS type and architecture unless otherwise specified
-GOOS ?= $(shell $(GO) env GOOS)
+NATIVE_GOOS := $(shell env -u GOOS $(GO) env GOOS)
+GOOS ?= $(NATIVE_GOOS)
+# Default to the native architecture type
+NATIVE_GOARCH := $(shell env -u GOARCH $(GO) env GOARCH)
+GOARCH ?= $(NATIVE_GOARCH)
ifeq ($(call err_if_empty,GOOS),windows)
BINSFX := .exe
SRCBINDIR := bin/windows
@@ -165,7 +168,7 @@ BINSFX := -remote
SRCBINDIR := bin
endif
# Necessary for nested-$(MAKE) calls and docs/remote-docs.sh
-export GOOS CGO_ENABLED BINSFX SRCBINDIR
+export GOOS GOARCH CGO_ENABLED BINSFX SRCBINDIR
define go-get
env GO111MODULE=off \
@@ -242,11 +245,11 @@ gofmt: ## Verify the source code gofmt
.PHONY: test/checkseccomp/checkseccomp
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
- $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
+ $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
.PHONY: test/testvol/testvol
test/testvol/testvol: .gopathok $(wildcard test/testvol/*.go)
- $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
+ $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/testvol
.PHONY: volume-plugin-test-image
volume-plugin-test-img:
@@ -254,7 +257,10 @@ volume-plugin-test-img:
.PHONY: test/goecho/goecho
test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
- $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+ $(GOCMD) build $(BUILDFLAGS) $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+
+test/version/version: .gopathok version/version.go
+ $(GO) build -o $@ ./test/version/
.PHONY: codespell
codespell:
@@ -292,10 +298,9 @@ ifeq (,$(findstring systemd,$(BUILDTAGS)))
Install libsystemd on Ubuntu or systemd-devel on rpm based \
distro for journald support."
endif
- CGO_ENABLED=$(CGO_ENABLED) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
- -ldflags '$(LDFLAGS_PODMAN)' \
+ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \
-tags "$(BUILDTAGS)" \
-o $@ ./cmd/podman
@@ -304,20 +309,16 @@ $(SRCBINDIR):
mkdir -p $(SRCBINDIR)
$(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
- CGO_ENABLED=$(CGO_ENABLED) \
- GOOS=$(GOOS) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
- -ldflags '$(LDFLAGS_PODMAN)' \
+ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \
-tags "${REMOTETAGS}" \
-o $@ ./cmd/podman
$(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum
- CGO_ENABLED=0 \
- GOOS=$(GOOS) \
- $(GO) build \
+ $(GOCMD) build \
$(BUILDFLAGS) \
- -ldflags '$(LDFLAGS_PODMAN_STATIC)' \
+ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN_STATIC)' \
-tags "${REMOTETAGS}" \
-o $@ ./cmd/podman
@@ -333,6 +334,7 @@ podman-remote-linux: ## Build podman-remote for Linux
$(MAKE) \
CGO_ENABLED=0 \
GOOS=linux \
+ GOARCH=$(GOARCH) \
bin/podman-remote
PHONY: podman-remote-static
@@ -350,6 +352,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
$(MAKE) \
CGO_ENABLED=0 \
GOOS=darwin \
+ GOARCH=$(GOARCH) \
bin/darwin/podman
###
@@ -359,7 +362,7 @@ podman-remote-darwin: ## Build podman-remote for macOS
.PHONY: generate-bindings
generate-bindings:
ifneq ($(GOOS),darwin)
- GO111MODULE=off $(GO) generate ./pkg/bindings/... ;
+ GO111MODULE=off $(GOCMD) generate ./pkg/bindings/... ;
endif
# DO NOT USE: use local-cross instead
@@ -370,7 +373,7 @@ bin/podman.cross.%: .gopathok
CGO_ENABLED=0 \
$(GO) build \
$(BUILDFLAGS) \
- -ldflags '$(LDFLAGS_PODMAN)' \
+ $(GO_LDFLAGS) '$(LDFLAGS_PODMAN)' \
-tags '$(BUILDTAGS_CROSS)' \
-o "$@" ./cmd/podman
@@ -409,9 +412,9 @@ completions: podman podman-remote
declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish [powershell]=%s.ps1);\
for shell in $${!outfiles[*]}; do \
for remote in "" "-remote"; do \
- podman="podman$$remote"; \
- outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \
- ./bin/$$podman completion $$shell >| $$outfile; \
+ podman="podman$$remote"; \
+ outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \
+ ./bin/$$podman completion $$shell >| $$outfile; \
done;\
done
@@ -429,10 +432,10 @@ $(MANPAGES): %: %.md .install.md2man docdir
### this ensures that manpages are renderd correctly
@sed -e 's/\((podman[^)]*\.md\(#.*\)\?)\)//g' \
- -e 's/\[\(podman[^]]*\)\]/\1/g' \
+ -e 's/\[\(podman[^]]*\)\]/\1/g' \
-e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \
- -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \
- -e 's/\\$$/ /g' $< | \
+ -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \
+ -e 's/\\$$/ /g' $< | \
$(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@)
.PHONY: docdir
@@ -444,12 +447,14 @@ docs: $(MANPAGES) ## Generate documentation
# docs/remote-docs.sh requires a locally executable 'podman-remote' binary
# in addition to the target-archetecture binary (if any).
-install-podman-remote-%-docs: podman-remote-$(shell env -i HOME=$$HOME PATH=$$PATH go env GOOS) docs $(MANPAGES)
+podman-remote-%-docs: podman-remote-$(NATIVE_GOOS)
+ $(eval GOOS := $*)
+ $(MAKE) docs $(MANPAGES)
rm -rf docs/build/remote
mkdir -p docs/build/remote
ln -sf $(CURDIR)/docs/source/markdown/links docs/build/man/
docs/remote-docs.sh \
- $* \
+ $(GOOS) \
docs/build/remote/$* \
$(if $(findstring windows,$*),docs/source/markdown,docs/build/man)
@@ -491,7 +496,7 @@ run-docker-py-tests:
-rm test/__init__.py
.PHONY: localunit
-localunit: test/goecho/goecho
+localunit: test/goecho/goecho test/version/version
rm -rf ${COVERAGE_PATH} && mkdir -p ${COVERAGE_PATH}
$(GOBIN)/ginkgo \
-r \
@@ -581,7 +586,8 @@ system.test-binary: .install.ginkgo
$(GO) test -c ./test/system
.PHONY: test-binaries
-test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.catatonit
+test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.catatonit test/version/version
+ @echo "Canonical source version: $(call err_if_empty,RELEASE_VERSION)"
.PHONY: tests-included
tests-included:
@@ -601,41 +607,72 @@ tests-expect-exit:
### Release/Packaging targets
###
-podman-release.tar.gz: binaries docs ## Build all binaries, docs., and installation tree, into a tarball.
+.PHONY: podman-release
+podman-release: podman-release-$(GOARCH).tar.gz # Build all Linux binaries for $GOARCH, docs., and installation tree, into a tarball.
+
+# The following two targets are nuanced and complex:
+# Cross-building the podman-remote documentation requires a functional
+# native architecture executable. However `make` only deals with
+# files/timestamps, it doesn't understand if an existing binary will
+# function on the system or not. This makes building cross-platform
+# releases incredibly accident-prone and fragile. The only practical
+# way to deal with this, is via multiple conditional (nested) `make`
+# calls along with careful manipulation of `$GOOS` and `$GOARCH`.
+
+podman-release-%.tar.gz: test/version/version
$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
- $(eval SUBDIR := podman-v$(RELEASE_NUMBER))
+ $(eval SUBDIR := podman-v$(call err_if_empty,RELEASE_NUMBER))
+ $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+ $(eval GOARCH := $*)
mkdir -p "$(TMPDIR)/$(SUBDIR)"
- $(MAKE) install.bin install.man \
- install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+ clean-binaries docs podman-remote-$(GOOS)-docs
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+ $(MAKE) CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) \
+ BUILDTAGS="$(BUILDTAGS_CROSS)" clean-binaries binaries; \
+ else \
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(GOARCH) binaries; \
+ fi
+ $(MAKE) $(_DSTARGS) install.bin-nobuild install.remote-nobuild install.man install.systemd
tar -czvf $@ --xattrs -C "$(TMPDIR)" "./$(SUBDIR)"
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
-rm -rf "$(TMPDIR)"
-podman-remote-release-%.zip: podman-remote-% install-podman-remote-%-docs ## Build podman-remote for GOOS=%, docs., and installation zip.
+podman-remote-release-%.zip: test/version/version ## Build podman-remote for %=$GOOS_$GOARCH, and docs. into an installation zip.
$(eval TMPDIR := $(shell mktemp -d podman_tmp_XXXX))
- $(eval SUBDIR := podman-$(RELEASE_NUMBER))
+ $(eval SUBDIR := podman-$(call err_if_empty,RELEASE_NUMBER))
+ $(eval _DSTARGS := "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr")
+ $(eval GOOS := $(firstword $(subst _, ,$*)))
+ $(eval GOARCH := $(lastword $(subst _, ,$*)))
+ $(eval _GOPLAT := GOOS=$(call err_if_empty,GOOS) GOARCH=$(call err_if_empty,GOARCH))
mkdir -p "$(TMPDIR)/$(SUBDIR)"
- $(MAKE) \
- GOOS=$* \
- DESTDIR=$(TMPDIR)/ \
- BINDIR=$(SUBDIR) \
- SELINUXOPT="" \
- install.remote-nobuild
- cp -r ./docs/build/remote/$* "$(TMPDIR)/$(SUBDIR)/docs/"
+ $(MAKE) GOOS=$(GOOS) GOARCH=$(NATIVE_GOARCH) \
+ clean-binaries podman-remote-$(GOOS)-docs
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then \
+ $(MAKE) CGO_ENABLED=0 $(GOPLAT) BUILDTAGS="$(BUILDTAGS_CROSS)" \
+ clean-binaries podman-remote-$(GOOS); \
+ else \
+ $(MAKE) $(GOPLAT) podman-remote-$(GOOS); \
+ fi
+ cp -r ./docs/build/remote/$(GOOS) "$(TMPDIR)/$(SUBDIR)/docs/"
cp ./contrib/remote/containers.conf "$(TMPDIR)/$(SUBDIR)/"
+ $(MAKE) $(GOPLAT) $(_DSTARGS) SELINUXOPT="" install.remote-nobuild
cd "$(TMPDIR)" && \
zip --recurse-paths "$(CURDIR)/$@" "./"
+ if [[ "$(GOARCH)" != "$(NATIVE_GOARCH)" ]]; then $(MAKE) clean-binaries; fi
-rm -rf "$(TMPDIR)"
.PHONY: podman.msi
-podman.msi: podman-v$(RELEASE_NUMBER).msi ## Build podman-remote, package for installation on Windows
-podman-v$(RELEASE_NUMBER).msi: podman-remote-windows install-podman-remote-windows-docs
+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
$(eval DOCFILE := docs/build/remote/windows)
find $(DOCFILE) -print | \
wixl-heat --var var.ManSourceDir --component-group ManFiles \
--directory-ref INSTALLDIR --prefix $(DOCFILE)/ > \
$(DOCFILE)/pages.wsx
- wixl -D VERSION=$(RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
- -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx
+ wixl -D VERSION=$(call err_if_empty,RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
+ -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx --arch x64
.PHONY: package
package: ## Build rpm packages
@@ -722,6 +759,8 @@ install.docker:
install.docker-docs-nobuild:
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
@@ -772,7 +811,7 @@ install.tools: .install.goimports .install.gitvalidation .install.md2man .instal
.PHONY: .install.golangci-lint
.install.golangci-lint: .gopathok
- VERSION=1.36.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
+ VERSION=1.36.0 GOBIN=$(GOBIN) ./hack/install_golangci.sh
.PHONY: .install.bats
.install.bats: .gopathok
@@ -819,8 +858,13 @@ uninstall:
rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.socket
rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.service
+.PHONY: clean-binaries
+clean-binaries: ## Remove platform/architecture specific binary files
+ rm -rf \
+ bin \
+
.PHONY: clean
-clean: ## Clean all make artifacts
+clean: clean-binaries ## Clean all make artifacts
rm -rf \
.gopathok \
_output \
@@ -828,10 +872,10 @@ clean: ## Clean all make artifacts
$(wildcard podman-remote*.zip) \
$(wildcard podman_tmp_*) \
$(wildcard podman*.tar.gz) \
- bin \
build \
test/checkseccomp/checkseccomp \
test/goecho/goecho \
+ test/version/version \
test/__init__.py \
test/testdata/redis-image \
libpod/container_ffjson.go \
diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md
index bdf8aca88..32d4c039e 100644
--- a/RELEASE_PROCESS.md
+++ b/RELEASE_PROCESS.md
@@ -234,16 +234,24 @@ spelled with complete minutiae.
1. Return to the Cirrus-CI Build page for the new release tag, confirm
(or wait for) it to complete, re-running any failed tasks as appropriate.
- 1. For anything other than an RC, download the new release artifacts
- (the binaries which were actually tested). Visit each of the
- "Build for ...", "Static Build", and "... Cross" tasks.
- 1. Under the "Artifacts" section of each task, click the "gosrc" item,
+ 1. For anything other than an RC, download the new release artifacts from CI
+ (the binaries which were actually tested). The items are
+ located under the *checks* tab in github for:
+
+ * `Cirrus CI / Alt Arch. Cross` - tarball for each architecture
+ * `Cirrus CI / OSX Cross` - two zip files (amd64 and arm64)
+ * `Cirrus CI / Windows Cross` - an `msi` file
+ * `Cirrus CI / Static Build` - the `bin/podman-remote` file
+
+ Under the "Artifacts" section of each task, click the "gosrc" link,
find and download the release archive (`zip`, `tar.gz` or `.msi`).
Save the the archive with a meaningful name, for example
`podman-v3.0.0.msi`.
1. For the "Static Build" task, find the compiled `podman` and `podman-remote`
- binaries under the "binary", "bin" links. Tar these files as
+ binaries under the "binary", then "bin" links. Tar these files as
`podman-static.tar.gz`.
+ 1. The `podman-vX.Y.Z.dmg` file is produced manually by someone in
+ posession of a developer signing key.
1. In the directory where you downloaded the archives, run
`sha256sum *.tar.gz *.zip *.msi > shasums` to generate SHA sums.
1. Go to `https://github.com/containers/podman/releases/tag/vX.Y.Z` and
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 2ea5fa10f..ea453a331 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -194,21 +194,14 @@ func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellComp
} else {
// suggested "registry.fedoraproject.org/f29/httpd:latest" as
// - "registry.fedoraproject.org/f29/httpd:latest"
- // - "registry.fedoraproject.org/f29/httpd"
// - "f29/httpd:latest"
- // - "f29/httpd"
// - "httpd:latest"
- // - "httpd"
paths := strings.Split(repo, "/")
for i := range paths {
suggestionWithTag := strings.Join(paths[i:], "/")
if strings.HasPrefix(suggestionWithTag, toComplete) {
suggestions = append(suggestions, suggestionWithTag)
}
- suggestionWithoutTag := strings.SplitN(strings.SplitN(suggestionWithTag, ":", 2)[0], "@", 2)[0]
- if strings.HasPrefix(suggestionWithoutTag, toComplete) {
- suggestions = append(suggestions, suggestionWithoutTag)
- }
}
}
}
@@ -778,10 +771,13 @@ func AutocompleteImageVolume(cmd *cobra.Command, args []string, toComplete strin
}
// AutocompleteLogDriver - Autocomplete log-driver options.
-// -> "journald", "none", "k8s-file"
+// -> "journald", "none", "k8s-file", "passthrough"
func AutocompleteLogDriver(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// don't show json-file
logDrivers := []string{define.JournaldLogging, define.NoLogging, define.KubernetesLogging}
+ if !registry.IsRemote() {
+ logDrivers = append(logDrivers, define.PassthroughLogging)
+ }
return logDrivers, cobra.ShellCompDirectiveNoFileComp
}
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 6200592b4..e490fa121 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -15,6 +15,18 @@ const sizeWithUnitFormat = "(format: `<number>[<unit>]`, where unit = b (bytes),
var containerConfig = registry.PodmanConfig()
+// ContainerToPodOptions takes the Container and Pod Create options, assigning the matching values back to podCreate for the purpose of the libpod API
+// For this function to succeed, the JSON tags in PodCreateOptions and ContainerCreateOptions need to match due to the Marshaling and Unmarshaling done.
+// The types of the options also need to match or else the unmarshaling will fail even if the tags match
+func ContainerToPodOptions(containerCreate *entities.ContainerCreateOptions, podCreate *entities.PodCreateOptions) error {
+ contMarshal, err := json.Marshal(containerCreate)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(contMarshal, podCreate)
+}
+
+// DefineCreateFlags declares and instantiates the container create flags
func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions, isInfra bool) {
createFlags := cmd.Flags()
@@ -144,14 +156,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = cmd.RegisterFlagCompletionFunc(cpusetMemsFlagName, completion.AutocompleteNone)
- deviceFlagName := "device"
- createFlags.StringSliceVar(
- &cf.Devices,
- deviceFlagName, devices(),
- "Add a host device to the container",
- )
- _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
-
deviceCgroupRuleFlagName := "device-cgroup-rule"
createFlags.StringSliceVar(
&cf.DeviceCGroupRule,
@@ -417,7 +421,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
pidsLimitFlagName := "pids-limit"
createFlags.Int64(
pidsLimitFlagName, pidsLimit(),
- "Tune container pids limit (set 0 for unlimited, -1 for server defaults)",
+ "Tune container pids limit (set -1 for unlimited)",
)
_ = cmd.RegisterFlagCompletionFunc(pidsLimitFlagName, completion.AutocompleteNone)
@@ -865,4 +869,11 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
volumeDesciption,
)
_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
+ deviceFlagName := "device"
+ createFlags.StringSliceVar(
+ &cf.Devices,
+ deviceFlagName, devices(),
+ "Add a host device to the container",
+ )
+ _ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
}
diff --git a/cmd/podman/common/create_test.go b/cmd/podman/common/create_test.go
new file mode 100644
index 000000000..17b47dd16
--- /dev/null
+++ b/cmd/podman/common/create_test.go
@@ -0,0 +1,53 @@
+package common_test
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/containers/podman/v3/cmd/podman/common"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPodOptions(t *testing.T) {
+ entry := "/test1"
+ exampleOptions := entities.ContainerCreateOptions{CPUS: 5.5, CPUSetCPUs: "0-4", Entrypoint: &entry, Hostname: "foo", Name: "testing123", Volume: []string{"/fakeVol1", "/fakeVol2"}, Net: &entities.NetOptions{CNINetworks: []string{"FakeNetwork"}}, PID: "ns:/proc/self/ns"}
+
+ podOptions := entities.PodCreateOptions{}
+ err := common.ContainerToPodOptions(&exampleOptions, &podOptions)
+ assert.Nil(t, err)
+
+ cc := reflect.ValueOf(&exampleOptions).Elem()
+ pc := reflect.ValueOf(&podOptions).Elem()
+
+ pcType := reflect.TypeOf(podOptions)
+ for i := 0; i < pc.NumField(); i++ {
+ podField := pc.FieldByIndex([]int{i})
+ podType := pcType.Field(i)
+ for j := 0; j < cc.NumField(); j++ {
+ containerField := cc.FieldByIndex([]int{j})
+ containerType := reflect.TypeOf(exampleOptions).Field(j)
+ tagPod := strings.Split(string(podType.Tag.Get("json")), ",")[0]
+ tagContainer := strings.Split(string(containerType.Tag.Get("json")), ",")[0]
+ if tagPod == tagContainer && (tagPod != "" && tagContainer != "") {
+ areEqual := true
+ if containerField.Kind() == podField.Kind() {
+ switch containerField.Kind() {
+ case reflect.Slice:
+ for i, w := range containerField.Interface().([]string) {
+ areEqual = podField.Interface().([]string)[i] == w
+ }
+ case reflect.String:
+ areEqual = (podField.String() == containerField.String())
+ case reflect.Bool:
+ areEqual = (podField.Bool() == containerField.Bool())
+ case reflect.Ptr:
+ areEqual = (reflect.DeepEqual(podField.Elem().Interface(), containerField.Elem().Interface()))
+ }
+ }
+ assert.True(t, areEqual)
+ }
+ }
+ }
+}
diff --git a/cmd/podman/containers/cleanup.go b/cmd/podman/containers/cleanup.go
index 98706c575..a3d339358 100644
--- a/cmd/podman/containers/cleanup.go
+++ b/cmd/podman/containers/cleanup.go
@@ -80,7 +80,7 @@ func cleanup(cmd *cobra.Command, args []string) error {
// is via syslog.
// As such, we need to logrus.Errorf our errors to ensure they
// are properly printed if --syslog is set.
- logrus.Errorf("Error running container cleanup: %v", err)
+ logrus.Errorf("Running container cleanup: %v", err)
return err
}
for _, r := range responses {
@@ -89,15 +89,15 @@ func cleanup(cmd *cobra.Command, args []string) error {
continue
}
if r.RmErr != nil {
- logrus.Errorf("Error removing container: %v", r.RmErr)
+ logrus.Errorf("Removing container: %v", r.RmErr)
errs = append(errs, r.RmErr)
}
if r.RmiErr != nil {
- logrus.Errorf("Error removing image: %v", r.RmiErr)
+ logrus.Errorf("Removing image: %v", r.RmiErr)
errs = append(errs, r.RmiErr)
}
if r.CleanErr != nil {
- logrus.Errorf("Error cleaning up container: %v", r.CleanErr)
+ logrus.Errorf("Cleaning up container: %v", r.CleanErr)
errs = append(errs, r.CleanErr)
}
}
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 8b27de53e..bfeeb7ebe 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgenutil"
"github.com/containers/podman/v3/pkg/util"
+ "github.com/mattn/go-isatty"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -161,7 +162,9 @@ func create(cmd *cobra.Command, args []string) error {
}
}
- fmt.Println(report.Id)
+ if cliVals.LogDriver != define.PassthroughLogging {
+ fmt.Println(report.Id)
+ }
return nil
}
@@ -188,6 +191,14 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
vals.UserNS = "private"
}
}
+ if cliVals.LogDriver == define.PassthroughLogging {
+ if isatty.IsTerminal(0) || isatty.IsTerminal(1) || isatty.IsTerminal(2) {
+ return vals, errors.New("the '--log-driver passthrough' option cannot be used on a TTY")
+ }
+ if registry.IsRemote() {
+ return vals, errors.New("the '--log-driver passthrough' option is not supported in remote mode")
+ }
+ }
if !isInfra {
if c.Flag("shm-size").Changed {
@@ -224,6 +235,10 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
if c.Flags().Changed("pids-limit") {
val := c.Flag("pids-limit").Value.String()
+ // Convert -1 to 0, so that -1 maps to unlimited pids limit
+ if val == "-1" {
+ val = "0"
+ }
pidsLimit, err := strconv.ParseInt(val, 10, 32)
if err != nil {
return vals, err
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index ff792b78b..9687cd5bd 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -221,7 +221,10 @@ func ps(cmd *cobra.Command, _ []string) error {
}
hdrs, format := createPsOut()
+
+ noHeading, _ := cmd.Flags().GetBool("noheading")
if cmd.Flags().Changed("format") {
+ noHeading = noHeading || !report.HasTable(listOpts.Format)
format = report.NormalizeFormat(listOpts.Format)
format = report.EnforceRange(format)
}
@@ -240,8 +243,7 @@ func ps(cmd *cobra.Command, _ []string) error {
defer w.Flush()
headers := func() error { return nil }
- noHeading, _ := cmd.Flags().GetBool("noheading")
- if !(noHeading || listOpts.Quiet || cmd.Flags().Changed("format")) {
+ if !noHeading {
headers = func() error {
return tmpl.Execute(w, hdrs)
}
@@ -298,9 +300,11 @@ func createPsOut() ([]map[string]string, string) {
"IPC": "ipc",
"MNT": "mnt",
"NET": "net",
+ "Networks": "networks",
"PIDNS": "pidns",
"Pod": "pod id",
"PodName": "podname", // undo camelcase space break
+ "RunningFor": "running for",
"UTS": "uts",
"User": "userns",
})
@@ -371,6 +375,10 @@ func (l psReporter) State() string {
// Status is a synonym for State()
func (l psReporter) Status() string {
+ hc := l.ListContainer.Status
+ if hc != "" {
+ return l.State() + " (" + hc + ")"
+ }
return l.State()
}
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index d14961829..071708b76 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -158,8 +158,13 @@ func run(cmd *cobra.Command, args []string) error {
runOpts.InputStream = nil
}
+ passthrough := cliVals.LogDriver == define.PassthroughLogging
+
// If attach is set, clear stdin/stdout/stderr and only attach requested
if cmd.Flag("attach").Changed {
+ if passthrough {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot specify --attach with --log-driver=passthrough")
+ }
runOpts.OutputStream = nil
runOpts.ErrorStream = nil
if !cliVals.Interactive {
@@ -179,6 +184,7 @@ func run(cmd *cobra.Command, args []string) error {
}
}
}
+
cliVals.PreserveFDs = runOpts.PreserveFDs
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
@@ -200,7 +206,7 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
- if runOpts.Detach {
+ if runOpts.Detach && !passthrough {
fmt.Println(report.Id)
return nil
}
diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go
index 6b48a342e..a42aa9f21 100644
--- a/cmd/podman/generate/generate.go
+++ b/cmd/podman/generate/generate.go
@@ -11,7 +11,7 @@ var (
// Command: podman _generate_
generateCmd = &cobra.Command{
Use: "generate",
- Short: "Generate structured data based on containers, pods or volumes.",
+ Short: "Generate structured data based on containers, pods or volumes",
Long: "Generate structured data (e.g., Kubernetes YAML or systemd units) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go
index 642da0c83..4c563ed27 100644
--- a/cmd/podman/images/build.go
+++ b/cmd/podman/images/build.go
@@ -131,7 +131,7 @@ func buildFlags(cmd *cobra.Command) {
// --pull flag
flag := budFlags.Lookup("pull")
if err := flag.Value.Set("true"); err != nil {
- logrus.Errorf("unable to set --pull to true: %v", err)
+ logrus.Errorf("Unable to set --pull to true: %v", err)
}
flag.DefValue = "true"
flag.Usage = "Always attempt to pull the image (errors are fatal)"
@@ -148,13 +148,13 @@ func buildFlags(cmd *cobra.Command) {
useLayersVal := useLayers()
buildOpts.Layers = useLayersVal == "true"
if err := flag.Value.Set(useLayersVal); err != nil {
- logrus.Errorf("unable to set --layers to %v: %v", useLayersVal, err)
+ logrus.Errorf("Unable to set --layers to %v: %v", useLayersVal, err)
}
flag.DefValue = useLayersVal
// --force-rm flag
flag = layerFlags.Lookup("force-rm")
if err := flag.Value.Set("true"); err != nil {
- logrus.Errorf("unable to set --force-rm to true: %v", err)
+ logrus.Errorf("Unable to set --force-rm to true: %v", err)
}
flag.DefValue = "true"
flags.AddFlagSet(&layerFlags)
@@ -162,7 +162,7 @@ func buildFlags(cmd *cobra.Command) {
// FromAndBud flags
fromAndBudFlags, err := buildahCLI.GetFromAndBudFlags(&buildOpts.FromAndBudResults, &buildOpts.UserNSResults, &buildOpts.NameSpaceResults)
if err != nil {
- logrus.Errorf("error setting up build flags: %v", err)
+ logrus.Errorf("Setting up build flags: %v", err)
os.Exit(1)
}
// --http-proxy flag
@@ -171,7 +171,7 @@ func buildFlags(cmd *cobra.Command) {
flag = fromAndBudFlags.Lookup("http-proxy")
buildOpts.HTTPProxy = false
if err := flag.Value.Set("false"); err != nil {
- logrus.Errorf("unable to set --https-proxy to %v: %v", false, err)
+ logrus.Errorf("Unable to set --https-proxy to %v: %v", false, err)
}
flag.DefValue = "false"
}
@@ -184,7 +184,7 @@ func buildFlags(cmd *cobra.Command) {
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)
+ logrus.Errorf("Unable to set --isolation to %v: %v", buildahDefine.OCI, err)
}
flag.DefValue = buildahDefine.OCI
_ = flags.MarkHidden("disable-content-trust")
@@ -228,7 +228,7 @@ func build(cmd *cobra.Command, args []string) error {
// Delete it later.
defer func() {
if err = os.RemoveAll(tempDir); err != nil {
- logrus.Errorf("error removing temporary directory %q: %v", contextDir, err)
+ logrus.Errorf("Removing temporary directory %q: %v", contextDir, err)
}
}()
contextDir = filepath.Join(tempDir, subDir)
diff --git a/cmd/podman/images/inspect.go b/cmd/podman/images/inspect.go
index 35c173a60..dd8cf8056 100644
--- a/cmd/podman/images/inspect.go
+++ b/cmd/podman/images/inspect.go
@@ -17,9 +17,9 @@ var (
Long: `Displays the low-level information of an image identified by name or ID.`,
RunE: inspectExec,
ValidArgsFunction: common.AutocompleteImages,
- Example: `podman inspect alpine
- podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
- podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
+ Example: `podman image inspect alpine
+ podman image inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
+ podman image inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
}
inspectOpts *entities.InspectOptions
)
diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go
index 8a484495a..6c39e5c69 100644
--- a/cmd/podman/images/prune.go
+++ b/cmd/podman/images/prune.go
@@ -41,6 +41,7 @@ func init() {
flags := pruneCmd.Flags()
flags.BoolVarP(&pruneOpts.All, "all", "a", false, "Remove all images not in use by containers, not just dangling ones")
+ flags.BoolVarP(&pruneOpts.External, "external", "", false, "Remove images even when they are used by external containers (e.g., by build containers)")
flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation")
filterFlagName := "filter"
@@ -80,7 +81,7 @@ func prune(cmd *cobra.Command, args []string) error {
func createPruneWarningMessage(pruneOpts entities.ImagePruneOptions) string {
question := "Are you sure you want to continue? [y/N] "
if pruneOpts.All {
- return "WARNING! This will remove all images without at least one container associated to them.\n" + question
+ return "WARNING! This command removes all images without at least one container associated with them.\n" + question
}
- return "WARNING! This will remove all dangling images.\n" + question
+ return "WARNING! This command removes all dangling images.\n" + question
}
diff --git a/cmd/podman/images/save.go b/cmd/podman/images/save.go
index 19dadb2ad..4f45cb912 100644
--- a/cmd/podman/images/save.go
+++ b/cmd/podman/images/save.go
@@ -84,6 +84,8 @@ func saveFlags(cmd *cobra.Command) {
flags.BoolVar(&saveOpts.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)")
+ flags.BoolVar(&saveOpts.OciAcceptUncompressedLayers, "uncompressed", false, "Accept uncompressed layers when copying OCI images")
+
formatFlagName := "format"
flags.StringVar(&saveOpts.Format, formatFlagName, define.V2s2Archive, "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type)")
_ = cmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteImageSaveFormat)
diff --git a/cmd/podman/images/utils_linux.go b/cmd/podman/images/utils_linux.go
index 5521abab4..f7c159415 100644
--- a/cmd/podman/images/utils_linux.go
+++ b/cmd/podman/images/utils_linux.go
@@ -24,7 +24,7 @@ func setupPipe() (string, func() <-chan error, error) {
err = unix.Mkfifo(pipePath, 0600)
if err != nil {
if e := os.RemoveAll(pipeDir); e != nil {
- logrus.Errorf("error removing named pipe: %q", e)
+ logrus.Errorf("Removing named pipe: %q", e)
}
return "", nil, errors.Wrapf(err, "error creating named pipe")
}
@@ -40,7 +40,7 @@ func setupPipe() (string, func() <-chan error, error) {
}()
return pipePath, func() <-chan error {
if e := os.RemoveAll(pipeDir); e != nil {
- logrus.Errorf("error removing named pipe: %q", e)
+ logrus.Errorf("Removing named pipe: %q", e)
}
return errc
}, nil
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index 4c7fa33a4..64b586388 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -220,7 +220,7 @@ func (i *inspector) inspect(namesOrIDs []string) error {
err = printTmpl(tmpType, row, data)
}
if err != nil {
- logrus.Errorf("Error printing inspect output: %v", err)
+ logrus.Errorf("Printing inspect output: %v", err)
}
if len(errs) > 0 {
diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index ec44a707d..adde887f7 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -3,6 +3,8 @@
package machine
import (
+ "fmt"
+
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/machine"
@@ -26,6 +28,7 @@ var (
var (
initOpts = machine.InitOptions{}
defaultMachineName = "podman-machine-default"
+ now bool
)
func init() {
@@ -39,7 +42,7 @@ func init() {
cpusFlagName := "cpus"
flags.Uint64Var(
&initOpts.CPUS,
- cpusFlagName, 1,
+ cpusFlagName, cfg.Machine.CPUs,
"Number of CPUs",
)
_ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
@@ -47,7 +50,7 @@ func init() {
diskSizeFlagName := "disk-size"
flags.Uint64Var(
&initOpts.DiskSize,
- diskSizeFlagName, 10,
+ diskSizeFlagName, cfg.Machine.DiskSize,
"Disk size in GB",
)
@@ -56,13 +59,19 @@ func init() {
memoryFlagName := "memory"
flags.Uint64VarP(
&initOpts.Memory,
- memoryFlagName, "m", 2048,
+ memoryFlagName, "m", cfg.Machine.Memory,
"Memory in MB",
)
_ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
+ flags.BoolVar(
+ &now,
+ "now", false,
+ "Start machine now",
+ )
+
ImagePathFlagName := "image-path"
- flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image")
+ flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image")
_ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault)
IgnitionPathFlagName := "ignition-path"
@@ -91,5 +100,15 @@ func initMachine(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- return vm.Init(initOpts)
+ err = vm.Init(initOpts)
+ if err != nil {
+ return err
+ }
+ if now {
+ err = vm.Start(initOpts.Name, machine.StartOptions{})
+ if err == nil {
+ fmt.Printf("Machine %q started successfully\n", initOpts.Name)
+ }
+ }
+ return err
}
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index d4360bb9b..95b7d860f 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -3,13 +3,16 @@
package machine
import (
+ "encoding/json"
"os"
"sort"
+ "strconv"
"time"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/report"
+ "github.com/containers/podman/v3/cmd/podman/common"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/machine"
@@ -40,10 +43,15 @@ type listFlagType struct {
}
type machineReporter struct {
- Name string
- Created string
- LastUp string
- VMType string
+ Name string
+ Default bool
+ Created string
+ Running bool
+ LastUp string
+ VMType string
+ CPUs uint64
+ Memory string
+ DiskSize string
}
func init() {
@@ -54,8 +62,8 @@ func init() {
flags := lsCmd.Flags()
formatFlagName := "format"
- flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n", "Format volume output using Go template")
- _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone)
+ flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\t{{.CPUs}}\t{{.Memory}}\t{{.DiskSize}}\n", "Format volume output using JSON or a Go template")
+ _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(machineReporter{}))
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
}
@@ -75,6 +83,21 @@ func list(cmd *cobra.Command, args []string) error {
sort.Slice(listResponse, func(i, j int) bool {
return listResponse[i].Running
})
+
+ if report.IsJSON(listFlag.format) {
+ machineReporter, err := toMachineFormat(listResponse)
+ if err != nil {
+ return err
+ }
+
+ b, err := json.Marshal(machineReporter)
+ if err != nil {
+ return err
+ }
+ os.Stdout.Write(b)
+ return nil
+ }
+
machineReporter, err := toHumanFormat(listResponse)
if err != nil {
return err
@@ -85,8 +108,11 @@ func list(cmd *cobra.Command, args []string) error {
func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
headers := report.Headers(machineReporter{}, map[string]string{
- "LastUp": "LAST UP",
- "VmType": "VM TYPE",
+ "LastUp": "LAST UP",
+ "VmType": "VM TYPE",
+ "CPUs": "CPUS",
+ "Memory": "MEMORY",
+ "DiskSize": "DISK SIZE",
})
row := report.NormalizeFormat(listFlag.format)
@@ -115,6 +141,42 @@ func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
return tmpl.Execute(w, responses)
}
+func strTime(t time.Time) string {
+ iso, err := t.MarshalText()
+ if err != nil {
+ return ""
+ }
+ return string(iso)
+}
+
+func strUint(u uint64) string {
+ return strconv.FormatUint(u, 10)
+}
+
+func toMachineFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
+ cfg, err := config.ReadCustomConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ machineResponses := make([]*machineReporter, 0, len(vms))
+ for _, vm := range vms {
+ response := new(machineReporter)
+ response.Default = vm.Name == cfg.Engine.ActiveService
+ response.Name = vm.Name
+ response.Running = vm.Running
+ response.LastUp = strTime(vm.LastUp)
+ response.Created = strTime(vm.CreatedAt)
+ response.VMType = vm.VMType
+ response.CPUs = vm.CPUs
+ response.Memory = strUint(vm.Memory * units.MiB)
+ response.DiskSize = strUint(vm.DiskSize * units.GiB)
+
+ machineResponses = append(machineResponses, response)
+ }
+ return machineResponses, nil
+}
+
func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
cfg, err := config.ReadCustomConfig()
if err != nil {
@@ -136,6 +198,9 @@ func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
}
response.Created = units.HumanDuration(time.Since(vm.CreatedAt)) + " ago"
response.VMType = vm.VMType
+ response.CPUs = vm.CPUs
+ response.Memory = units.HumanSize(float64(vm.Memory) * units.MiB)
+ response.DiskSize = units.HumanSize(float64(vm.DiskSize) * units.GiB)
humanResponses = append(humanResponses, response)
}
diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go
index 84e9e88ab..da0a09338 100644
--- a/cmd/podman/machine/ssh.go
+++ b/cmd/podman/machine/ssh.go
@@ -5,6 +5,7 @@ package machine
import (
"net/url"
+ "github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/machine"
@@ -15,7 +16,7 @@ import (
var (
sshCmd = &cobra.Command{
- Use: "ssh [NAME] [COMMAND [ARG ...]]",
+ Use: "ssh [options] [NAME] [COMMAND [ARG ...]]",
Short: "SSH into an existing machine",
Long: "SSH into a managed virtual machine ",
RunE: ssh,
@@ -35,6 +36,10 @@ func init() {
Command: sshCmd,
Parent: machineCmd,
})
+ flags := sshCmd.Flags()
+ usernameFlagName := "username"
+ flags.StringVar(&sshOpts.Username, usernameFlagName, "", "Username to use when ssh-ing into the VM.")
+ _ = sshCmd.RegisterFlagCompletionFunc(usernameFlagName, completion.AutocompleteNone)
}
func ssh(cmd *cobra.Command, args []string) error {
@@ -48,13 +53,6 @@ func ssh(cmd *cobra.Command, args []string) error {
// Set the VM to default
vmName := defaultMachineName
- // If we're not given a VM name, use the remote username from the connection config
- if len(args) == 0 {
- sshOpts.Username, err = remoteConnectionUsername()
- if err != nil {
- return err
- }
- }
// If len is greater than 0, it means we may have been
// provided the VM name. If so, we check. The VM name,
// if provided, must be in args[0].
@@ -68,10 +66,6 @@ func ssh(cmd *cobra.Command, args []string) error {
if validVM {
vmName = args[0]
} else {
- sshOpts.Username, err = remoteConnectionUsername()
- if err != nil {
- return err
- }
sshOpts.Args = append(sshOpts.Args, args[0])
}
}
@@ -83,14 +77,17 @@ func ssh(cmd *cobra.Command, args []string) error {
if validVM {
sshOpts.Args = args[1:]
} else {
- sshOpts.Username, err = remoteConnectionUsername()
- if err != nil {
- return err
- }
sshOpts.Args = args
}
}
+ if !validVM && sshOpts.Username == "" {
+ sshOpts.Username, err = remoteConnectionUsername()
+ if err != nil {
+ return err
+ }
+ }
+
switch vmType {
default:
vm, err = qemu.LoadVMByName(vmName)
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
index c0e5b9720..4f3e86fc9 100644
--- a/cmd/podman/networks/inspect.go
+++ b/cmd/podman/networks/inspect.go
@@ -12,7 +12,7 @@ var (
networkinspectDescription = `Inspect network`
networkinspectCommand = &cobra.Command{
Use: "inspect [options] NETWORK [NETWORK...]",
- Short: "network inspect",
+ Short: "Displays the raw CNI network configuration for one or more networks.",
Long: networkinspectDescription,
RunE: networkInspect,
Example: `podman network inspect podman`,
diff --git a/cmd/podman/play/play.go b/cmd/podman/play/play.go
index f121d6a2d..d676bd701 100644
--- a/cmd/podman/play/play.go
+++ b/cmd/podman/play/play.go
@@ -10,7 +10,7 @@ var (
// Command: podman _play_
playCmd = &cobra.Command{
Use: "play",
- Short: "Play containers, pods or volumes from a structured file.",
+ Short: "Play containers, pods or volumes from a structured file",
Long: "Play structured data (e.g., Kubernetes YAML) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 7000c92c8..ca73a8356 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -132,7 +132,6 @@ func create(cmd *cobra.Command, args []string) error {
createOptions.Share = nil
} else {
// reassign certain optios for lbpod api, these need to be populated in spec
- MapOptions()
flags := cmd.Flags()
infraOptions.Net, err = common.NetFlagsToNetOptions(nil, *flags, false)
if err != nil {
@@ -142,13 +141,11 @@ func create(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- createOptions.Net = infraOptions.Net
createOptions.Share = strings.Split(share, ",")
if cmd.Flag("infra-command").Changed {
// Only send content to server side if user changed defaults
cmdIn, err := cmd.Flags().GetString("infra-command")
infraOptions.Entrypoint = &cmdIn
- createOptions.InfraCommand = cmdIn
if err != nil {
return err
}
@@ -161,6 +158,10 @@ func create(cmd *cobra.Command, args []string) error {
return err
}
}
+ err = common.ContainerToPodOptions(&infraOptions, &createOptions)
+ if err != nil {
+ return err
+ }
}
if cmd.Flag("pod-id-file").Changed {
@@ -196,8 +197,8 @@ func create(cmd *cobra.Command, args []string) error {
if createOptions.Cpus > float64(numCPU) {
createOptions.Cpus = float64(numCPU)
}
- copy := createOptions.CpusetCpus
- cpuSet := createOptions.Cpus
+ copy := infraOptions.CPUSetCPUs
+ cpuSet := infraOptions.CPUS
if cpuSet == 0 {
cpuSet = float64(sysinfo.NumCPU())
}
@@ -217,10 +218,10 @@ func create(cmd *cobra.Command, args []string) error {
if core > int(cpuSet) {
if copy == "" {
copy = "0-" + strconv.Itoa(int(cpuSet))
- createOptions.CpusetCpus = copy
+ infraOptions.CPUSetCPUs = copy
break
} else {
- createOptions.CpusetCpus = copy
+ infraOptions.CPUSetCPUs = copy
break
}
} else if ind != 0 {
@@ -229,6 +230,8 @@ func create(cmd *cobra.Command, args []string) error {
copy = "" + strconv.Itoa(core)
}
}
+ createOptions.Cpus = infraOptions.CPUS
+ createOptions.CpusetCpus = infraOptions.CPUSetCPUs
podSpec := specgen.NewPodSpecGenerator()
podSpec, err = entities.ToPodSpecGen(*podSpec, &createOptions)
if err != nil {
@@ -248,11 +251,8 @@ func create(cmd *cobra.Command, args []string) error {
}
podSpec.InfraImage = imageName
if infraOptions.Entrypoint != nil {
- createOptions.InfraCommand = *infraOptions.Entrypoint
+ createOptions.InfraCommand = infraOptions.Entrypoint
}
- infraOptions.CPUS = createOptions.Cpus
- infraOptions.CPUSetCPUs = createOptions.CpusetCpus
- infraOptions.PID = createOptions.Pid
podSpec.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
podSpec.InfraContainerSpec.RawImageName = rawImageName
podSpec.InfraContainerSpec.NetworkOptions = podSpec.NetworkOptions
@@ -290,13 +290,3 @@ func replacePod(name string) error {
}
return removePods([]string{name}, rmOptions, false)
}
-
-func MapOptions() {
- createOptions.Cpus = infraOptions.CPUS
- createOptions.CpusetCpus = infraOptions.CPUSetCPUs
- createOptions.Hostname = infraOptions.Hostname
- createOptions.InfraConmonPidFile = infraOptions.ConmonPIDFile
- createOptions.InfraName = infraOptions.Name
- createOptions.Pid = infraOptions.PID
- createOptions.Volume = infraOptions.Volume
-}
diff --git a/cmd/podman/registry/config.go b/cmd/podman/registry/config.go
index 50e488b02..b512ba341 100644
--- a/cmd/podman/registry/config.go
+++ b/cmd/podman/registry/config.go
@@ -89,12 +89,7 @@ func newPodmanConfig() {
// use for the containers.conf configuration file.
func setXdgDirs() error {
if !rootless.IsRootless() {
- // unset XDG_RUNTIME_DIR for root
- // Sometimes XDG_RUNTIME_DIR is set to /run/user/0 sometimes it is unset,
- // the inconsistency is causing issues for the dnsname plugin.
- // It is already set to an empty string for conmon so lets do the same
- // for podman. see #10806 and #10745
- return os.Unsetenv("XDG_RUNTIME_DIR")
+ return nil
}
// Setup XDG_RUNTIME_DIR
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 02e6dcd27..eb30f1ef6 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -92,6 +92,11 @@ func Execute() {
if registry.GetExitCode() == 0 {
registry.SetExitCode(define.ExecErrorCodeGeneric)
}
+ if registry.IsRemote() {
+ if strings.Contains(err.Error(), "unable to connect to Podman") {
+ fmt.Fprintln(os.Stderr, "Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM")
+ }
+ }
fmt.Fprintln(os.Stderr, formatError(err))
}
os.Exit(registry.GetExitCode())
@@ -175,7 +180,7 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error {
// Hard code TMPDIR functions to use /var/tmp, if user did not override
if _, ok := os.LookupEnv("TMPDIR"); !ok {
if tmpdir, err := cfg.ImageCopyTmpDir(); err != nil {
- logrus.Warnf("failed to retrieve default tmp dir: %s", err.Error())
+ logrus.Warnf("Failed to retrieve default tmp dir: %s", err.Error())
} else {
os.Setenv("TMPDIR", tmpdir)
}
@@ -313,7 +318,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
pFlags := cmd.PersistentFlags()
if registry.IsRemote() {
if err := lFlags.MarkHidden("remote"); err != nil {
- logrus.Warnf("unable to mark --remote flag as hidden: %s", err.Error())
+ logrus.Warnf("Unable to mark --remote flag as hidden: %s", err.Error())
}
opts.Remote = true
} else {
@@ -387,7 +392,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
"trace",
} {
if err := pFlags.MarkHidden(f); err != nil {
- logrus.Warnf("unable to mark %s flag as hidden: %s", f, err.Error())
+ logrus.Warnf("Unable to mark %s flag as hidden: %s", f, err.Error())
}
}
}
diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go
index e09e2d5e5..5565ea2f9 100644
--- a/cmd/podman/system/prune.go
+++ b/cmd/podman/system/prune.go
@@ -113,15 +113,15 @@ func prune(cmd *cobra.Command, args []string) error {
func createPruneWarningMessage(pruneOpts entities.SystemPruneOptions) string {
if pruneOpts.All {
- return `WARNING! This will remove:
+ return `WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container%s
- - all images without at least one container associated to them
+ - all images without at least one container associated with them
- all build cache
%s`
}
- return `WARNING! This will remove:
+ return `WARNING! This command removes:
- all stopped containers
- all networks not used by at least one container%s
- all dangling images
diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go
index a30f43839..99a6b1e1e 100644
--- a/cmd/podman/system/service.go
+++ b/cmd/podman/system/service.go
@@ -52,8 +52,9 @@ func init() {
flags := srvCmd.Flags()
+ cfg := registry.PodmanConfig()
timeFlagName := "time"
- flags.Int64VarP(&srvArgs.Timeout, timeFlagName, "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout")
+ flags.Int64VarP(&srvArgs.Timeout, timeFlagName, "t", int64(cfg.Engine.ServiceTimeout), "Time until the service session expires in seconds. Use 0 to disable the timeout")
_ = srvCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone)
flags.StringVarP(&srvArgs.CorsHeaders, "cors", "", "", "Set CORS Headers")
_ = srvCmd.RegisterFlagCompletionFunc("cors", completion.AutocompleteNone)
@@ -73,7 +74,7 @@ func service(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- logrus.Infof("using API endpoint: '%s'", apiURI)
+ logrus.Infof("Using API endpoint: '%s'", apiURI)
// Clean up any old existing unix domain socket
if len(apiURI) > 0 {
uri, err := url.Parse(apiURI)
@@ -119,7 +120,7 @@ func resolveAPIURI(_url []string) (string, error) {
case len(_url) > 0 && _url[0] != "":
return _url[0], nil
case systemd.SocketActivated():
- logrus.Info("using systemd socket activation to determine API endpoint")
+ logrus.Info("Using systemd socket activation to determine API endpoint")
return "", nil
case rootless.IsRootless():
xdg, err := util.GetRuntimeDir()
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index c1972b90f..22a66dd08 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -205,10 +205,12 @@ function _run_build() {
# Ensure always start from clean-slate with all vendor modules downloaded
make clean
make vendor
- make podman-release.tar.gz # includes podman, podman-remote, and docs
+ make podman-release # includes podman, podman-remote, and docs
}
function _run_altbuild() {
+ local -a arches
+ local arch
req_env_vars ALT_NAME
# Defined in .cirrus.yml
# shellcheck disable=SC2154
@@ -221,7 +223,7 @@ function _run_altbuild() {
make build-all-new-commits GIT_BASE_BRANCH=origin/$DEST_BRANCH
;;
*Windows*)
- make podman-remote-release-windows.zip
+ make podman-remote-release-windows_amd64.zip
make podman.msi
;;
*Without*)
@@ -232,7 +234,21 @@ function _run_altbuild() {
rpmbuild --rebuild ./podman-*.src.rpm
;;
Alt*Cross)
- make local-cross
+ arches=(\
+ amd64
+ ppc64le
+ arm
+ arm64
+ 386
+ s390x
+ mips
+ mipsle
+ mips64
+ mips64le)
+ for arch in "${arches[@]}"; do
+ msg "Building release archive for $arch"
+ make podman-release-${arch}.tar.gz GOARCH=$arch
+ done
;;
*Static*)
req_env_vars CTR_FQIN
@@ -270,6 +286,23 @@ function _run_release() {
msg "All OK"
}
+
+function _run_gitlab() {
+ rootless_uid=$(id -u)
+ systemctl enable --now --user podman.socket
+ export DOCKER_HOST=unix:///run/user/${rootless_uid}/podman/podman.sock
+ export CONTAINER_HOST=$DOCKER_HOST
+ cd $GOPATH/src/gitlab.com/gitlab-org/gitlab-runner
+ set +e
+ go test -v ./executors/docker |& tee $GOSRC/gitlab-runner-podman.log
+ ret=$?
+ set -e
+ # This file is collected and parsed by Cirrus-CI so must be in $GOSRC
+ cat $GOSRC/gitlab-runner-podman.log | \
+ go-junit-report > $GOSRC/gitlab-runner-podman.xml
+ return $ret
+}
+
logformatter() {
if [[ "$CI" == "true" ]]; then
# Use similar format as human-friendly task name from .cirrus.yml
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 41b155943..ef1f83024 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -243,6 +243,44 @@ case "$TEST_FLAVOR" in
install_test_configs
;;
+ gitlab)
+ # This only runs on Ubuntu for now
+ if [[ "$OS_RELEASE_ID" != "ubuntu" ]]; then
+ die "This test only runs on Ubuntu due to sheer laziness"
+ fi
+
+ # Ref: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27270#note_499585550
+
+ remove_packaged_podman_files
+ make install PREFIX=/usr ETCDIR=/etc
+
+ # Need to re-build lists (removed during image production)
+ ooe.sh apt-get -qq -y update
+ msg "Installing previously downloaded/cached packages"
+ # N/B: Tests check/expect `docker info` output, and this `!= podman info`
+ ooe.sh apt-get install --yes --no-download --ignore-missing containerd.io docker-ce docker-ce-cli
+
+ msg "Disabling docker service and socket activation"
+ systemctl stop docker.service docker.socket
+ systemctl disable docker.service docker.socket
+ rm -rf /run/docker*
+ # Guarantee the docker daemon can't be started, even by accident
+ rm -vf $(type -P dockerd)
+
+ msg "Obtaining necessary gitlab-runner testing bits"
+ slug="gitlab.com/gitlab-org/gitlab-runner"
+ helper_fqin="registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest-pwsh"
+ ssh="ssh $ROOTLESS_USER@localhost -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no env GOPATH=$GOPATH"
+ showrun $ssh go get -u github.com/jstemmer/go-junit-report
+ showrun $ssh git clone https://$slug $GOPATH/src/$slug
+ showrun $ssh make -C $GOPATH/src/$slug development_setup
+ showrun $ssh bash -c "'cd $GOPATH/src/$slug && GOPATH=$GOPATH go get .'"
+
+ showrun $ssh podman pull $helper_fqin
+ # Tests expect image with this exact name
+ showrun $ssh podman tag $helper_fqin \
+ docker.io/gitlab/gitlab-runner-helper:x86_64-latest-pwsh
+ ;;
swagger) ;& # use next item
consistency) make clean ;;
release) ;;
diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs
index 451dd565d..4136e2cc4 100644
--- a/contrib/msi/podman.wxs
+++ b/contrib/msi/podman.wxs
@@ -11,19 +11,19 @@
<Product Name="Podman $(var.VERSION)" Id="*" UpgradeCode="696BAB5D-CA1F-4B05-B123-320F245B8D6D" Version="$(var.VERSION)" Language="1033" Manufacturer="Red Hat Inc.">
- <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="100" Compressed="yes"/>
+ <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="200" Compressed="yes"/>
<Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/>
<Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/>
<Directory Id="TARGETDIR" Name="SourceDir">
- <Directory Id="ProgramFilesFolder" Name="PFiles">
+ <Directory Id="ProgramFiles64Folder" Name="PFiles">
<Directory Id="RedHatPFiles" Name="RedHat">
<Directory Id="INSTALLDIR" Name="Podman">
- <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82">
+ <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82" Win64="Yes">
<CreateFolder/>
</Component>
- <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714">
+ <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714" Win64="Yes">
<File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman.exe" Source="bin/windows/podman.exe" KeyPath="yes"/>
</Component>
</Directory>
diff --git a/contrib/podmanimage/README.md b/contrib/podmanimage/README.md
index b7be328c7..2452d7293 100644
--- a/contrib/podmanimage/README.md
+++ b/contrib/podmanimage/README.md
@@ -66,3 +66,7 @@ exit
the fuse kernel module has not been loaded on your host system. Use the command `modprobe fuse` to load the
module and then run the container image. To enable this automatically at boot time, you can add a configuration
file to `/etc/modules.load.d`. See `man modules-load.d` for more details.
+
+### Blog Post with Details
+
+Dan Walsh wrote a blog post on the [Enable Sysadmin](https://www.redhat.com/sysadmin/) site titled [How to use Podman inside of a container](https://www.redhat.com/sysadmin/podman-inside-container). In it, he details how to use these images as a rootful and as a rootless user. Please refer to this blog for more detailed information.
diff --git a/docs/dckrman.sh b/docs/dckrman.sh
index c69524a7e..18fb364bf 100755
--- a/docs/dckrman.sh
+++ b/docs/dckrman.sh
@@ -4,3 +4,4 @@ for i in $@; do
filename=$(echo $i | sed 's/podman/docker/g')
echo .so man1/$b > $filename
done
+echo .so man5/containerfile.5 > $(dirname $1)/dockerfile.5
diff --git a/docs/source/markdown/links/podman-container-inspect.1 b/docs/source/markdown/links/podman-container-inspect.1
deleted file mode 100644
index 261043845..000000000
--- a/docs/source/markdown/links/podman-container-inspect.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-inspect.1
diff --git a/docs/source/markdown/links/podman-image-inspect.1 b/docs/source/markdown/links/podman-image-inspect.1
deleted file mode 100644
index 261043845..000000000
--- a/docs/source/markdown/links/podman-image-inspect.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-inspect.1
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 98c8251b4..15d936d17 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -64,8 +64,10 @@ discarded when writing images in Docker formats.
#### **--arch**=*arch*
-Set the ARCH of the image to the provided value instead of the architecture of
-the host.
+Set the architecture of the image to be built, and that of the base image to be
+pulled, if the build uses one, to the provided value instead of using the
+architecture of the build host. (Examples: arm, arm64, 386, amd64, ppc64le,
+s390x)
#### **--authfile**=*path*
@@ -321,7 +323,8 @@ Pass through HTTP Proxy environment variables.
#### **--iidfile**=*ImageIDfile*
-Write the image ID to the file.
+Write the built image's ID to the file. When `--platform` is specified more
+than once, attempting to use this option will trigger an error.
#### **--ignorefile**
@@ -389,6 +392,7 @@ Name of the manifest list to which the image will be added. Creates the manifest
if it does not exist. This option is useful for building multi architecture images.
#### **--memory**, **-m**=*LIMIT*
+
Memory limit (format: `<number>[<unit>]`, where unit = b (bytes), k (kilobytes),
m (megabytes), or g (gigabytes))
@@ -430,8 +434,9 @@ with a new set of cached layers.
#### **--os**=*string*
-Set the OS to the provided value instead of the current operating system of the
-host.
+Set the OS of the image to be built, and that of the base image to be pulled,
+if the build uses one, instead of using the current operating system of the
+build host.
#### **--pid**=*pid*
@@ -442,11 +447,28 @@ that the PID namespace in which `podman` itself is being run should be reused,
or it can be the path to a PID namespace which is already in use by another
process.
-#### **--platform**="Linux"
+#### **--platform**="OS/ARCH[/VARIANT][,...]"
+
+Set the OS/ARCH of the built image (and its base image, if your build uses one)
+to the provided value instead of using the current operating system and
+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
+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.
+
+OS/ARCH pairs are those used by the Go Programming Language. In several cases
+the ARCH value for a platform differs from one produced by other tools such as
+the `arch` command. Valid OS and architecture name combinations are listed as
+values for $GOOS and $GOARCH at https://golang.org/doc/install/source#environment,
+and can also be found by running `go tool dist list`.
-This option has no effect on the build. Other container engines use this option
-to control the execution platform for the build (e.g., Windows, Linux) which is
-not required for Buildah as it supports only Linux.
+While `podman build` is happy to use base images and build images for any
+platform that exists, `RUN` instructions will not be able to succeed without
+the help of emulation provided by packages like `qemu-user-static`.
#### **--pull**
@@ -486,7 +508,6 @@ commands specified by the **RUN** instruction.
Note: You can also override the default runtime by setting the BUILDAH\_RUNTIME
environment variable. `export BUILDAH_RUNTIME=/usr/local/bin/runc`
-
#### **--secret**=**id=id,src=path**
Pass secret information to be used in the Containerfile for building images
@@ -497,7 +518,6 @@ To later use the secret, use the --mount flag in a `RUN` instruction within a `C
`RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret`
-
#### **--security-opt**=*option*
Security Options
@@ -697,7 +717,9 @@ process.
#### **--variant**=""
-Set the architecture variant of the image to be pulled.
+Set the architecture variant of the image to be built, and that of the base
+image to be pulled, if the build uses one, to the provided value instead of
+using the architecture variant of the build host.
#### **--volume**, **-v**[=*[HOST-DIR:CONTAINER-DIR[:OPTIONS]]*]
@@ -858,7 +880,7 @@ $ podman build --layers --force-rm -t imageName .
$ podman build --no-cache --rm=false -t imageName .
```
-### Building an multi-architecture image using a --manifest option (Requires emulation software)
+### Building a multi-architecture image using the --manifest option (requires emulation software)
```
$ podman build --arch arm --manifest myimage /tmp/mysrc
@@ -866,6 +888,10 @@ $ podman build --arch arm --manifest myimage /tmp/mysrc
$ podman build --arch amd64 --manifest myimage /tmp/mysrc
$ podman build --arch s390x --manifest myimage /tmp/mysrc
+
+$ podman build --platform linux/s390x,linux/ppc64le,linux/amd64 --manifest myimage /tmp/mysrc
+
+$ podman build --platform linux/arm64 --platform linux/amd64 --manifest myimage /tmp/mysrc
```
### Building an image using a URL, Git repo, or archive
diff --git a/docs/source/markdown/podman-container-inspect.1.md b/docs/source/markdown/podman-container-inspect.1.md
new file mode 100644
index 000000000..72b7cef3b
--- /dev/null
+++ b/docs/source/markdown/podman-container-inspect.1.md
@@ -0,0 +1,318 @@
+% podman-container-inspect(1)
+
+## NAME
+podman\-container\-inspect - Display a container's configuration
+
+## SYNOPSIS
+**podman container inspect** [*options*] *container* [*container* ...]
+
+## DESCRIPTION
+
+This displays the low-level information on containers identified by name or ID. By default, this will render
+all results in a JSON array. If a format is specified, the given template will be executed for each result.
+
+## OPTIONS
+
+#### **--format**, **-f**=*format*
+
+Format the output using the given Go template.
+The keys of the returned JSON can be used as the values for the --format flag (see examples below).
+
+#### **--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.)
+
+#### **--size**, **-s**
+
+In addition to normal output, display the total file size if the type is a container.
+
+
+## EXAMPLE
+
+```
+$ podman container inspect foobar
+[
+ {
+ "Id": "99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6",
+ "Created": "2021-09-16T06:09:08.936623325-04:00",
+ "Path": "echo",
+ "Args": [
+ "hi"
+ ],
+ "State": {
+ "OciVersion": "1.0.2-dev",
+ "Status": "exited",
+ "Running": false,
+ "Paused": false,
+ "Restarting": false,
+ "OOMKilled": false,
+ "Dead": false,
+ "Pid": 0,
+ "ExitCode": 0,
+ "Error": "",
+ "StartedAt": "2021-09-16T06:09:09.033564436-04:00",
+ "FinishedAt": "2021-09-16T06:09:09.036184314-04:00",
+ "Healthcheck": {
+ "Status": "",
+ "FailingStreak": 0,
+ "Log": null
+ }
+ },
+ "Image": "14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab",
+ "ImageName": "docker.io/library/alpine:latest",
+ "Rootfs": "",
+ "Pod": "",
+ "ResolvConfPath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/resolv.conf",
+ "HostnamePath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/hostname",
+ "HostsPath": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/hosts",
+ "StaticDir": "/home/dwalsh/.local/share/containers/storage/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata",
+ "OCIConfigPath": "/home/dwalsh/.local/share/containers/storage/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/config.json",
+ "OCIRuntime": "crun",
+ "ConmonPidFile": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/conmon.pid",
+ "PidFile": "/run/user/3267/containers/overlay-containers/99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6/userdata/pidfile",
+ "Name": "foobar",
+ "RestartCount": 0,
+ "Driver": "overlay",
+ "MountLabel": "system_u:object_r:container_file_t:s0:c25,c695",
+ "ProcessLabel": "system_u:system_r:container_t:s0:c25,c695",
+ "AppArmorProfile": "",
+ "EffectiveCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FOWNER",
+ "CAP_FSETID",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SETFCAP",
+ "CAP_SETGID",
+ "CAP_SETPCAP",
+ "CAP_SETUID",
+ "CAP_SYS_CHROOT"
+ ],
+ "BoundingCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FOWNER",
+ "CAP_FSETID",
+ "CAP_KILL",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SETFCAP",
+ "CAP_SETGID",
+ "CAP_SETPCAP",
+ "CAP_SETUID",
+ "CAP_SYS_CHROOT"
+ ],
+ "ExecIDs": [],
+ "GraphDriver": {
+ "Name": "overlay",
+ "Data": {
+ "LowerDir": "/home/dwalsh/.local/share/containers/storage/overlay/e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68/diff",
+ "UpperDir": "/home/dwalsh/.local/share/containers/storage/overlay/8f3d70434a3db17410ec4710caf4f251f3e4ed0a96a08124e4b3d4af0a0ea300/diff",
+ "WorkDir": "/home/dwalsh/.local/share/containers/storage/overlay/8f3d70434a3db17410ec4710caf4f251f3e4ed0a96a08124e4b3d4af0a0ea300/work"
+ }
+ },
+ "Mounts": [],
+ "Dependencies": [],
+ "NetworkSettings": {
+ "EndpointID": "",
+ "Gateway": "",
+ "IPAddress": "",
+ "IPPrefixLen": 0,
+ "IPv6Gateway": "",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "MacAddress": "",
+ "Bridge": "",
+ "SandboxID": "",
+ "HairpinMode": false,
+ "LinkLocalIPv6Address": "",
+ "LinkLocalIPv6PrefixLen": 0,
+ "Ports": {},
+ "SandboxKey": ""
+ },
+ "ExitCommand": [
+ "/usr/bin/podman",
+ "--root",
+ "/home/dwalsh/.local/share/containers/storage",
+ "--runroot",
+ "/run/user/3267/containers",
+ "--log-level",
+ "warning",
+ "--cgroup-manager",
+ "systemd",
+ "--tmpdir",
+ "/run/user/3267/libpod/tmp",
+ "--runtime",
+ "crun",
+ "--storage-driver",
+ "overlay",
+ "--events-backend",
+ "journald",
+ "container",
+ "cleanup",
+ "99f66530fe9c7249f7cf29f78e8661669d5831cbe4ee80ea757d5e922dd6a8a6"
+ ],
+ "Namespace": "",
+ "IsInfra": false,
+ "Config": {
+ "Hostname": "99f66530fe9c",
+ "Domainname": "",
+ "User": "",
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "AttachStderr": false,
+ "Tty": false,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "Env": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=xterm",
+ "container=podman",
+ "HOME=/root",
+ "HOSTNAME=99f66530fe9c"
+ ],
+ "Cmd": [
+ "echo",
+ "hi"
+ ],
+ "Image": "docker.io/library/alpine:latest",
+ "Volumes": null,
+ "WorkingDir": "/",
+ "Entrypoint": "",
+ "OnBuild": null,
+ "Labels": null,
+ "Annotations": {
+ "io.container.manager": "libpod",
+ "io.kubernetes.cri-o.Created": "2021-09-16T06:09:08.936623325-04:00",
+ "io.kubernetes.cri-o.TTY": "false",
+ "io.podman.annotations.autoremove": "FALSE",
+ "io.podman.annotations.init": "FALSE",
+ "io.podman.annotations.privileged": "FALSE",
+ "io.podman.annotations.publish-all": "FALSE",
+ "org.opencontainers.image.stopSignal": "15"
+ },
+ "StopSignal": 15,
+ "CreateCommand": [
+ "podman",
+ "run",
+ "--name",
+ "foobar",
+ "alpine",
+ "echo",
+ "hi"
+ ],
+ "Timezone": "local",
+ "Umask": "0022",
+ "Timeout": 0,
+ "StopTimeout": 10
+ },
+ "HostConfig": {
+ "Binds": [],
+ "CgroupManager": "systemd",
+ "CgroupMode": "private",
+ "ContainerIDFile": "",
+ "LogConfig": {
+ "Type": "journald",
+ "Config": null,
+ "Path": "",
+ "Tag": "",
+ "Size": "0B"
+ },
+ "NetworkMode": "slirp4netns",
+ "PortBindings": {},
+ "RestartPolicy": {
+ "Name": "",
+ "MaximumRetryCount": 0
+ },
+ "AutoRemove": false,
+ "VolumeDriver": "",
+ "VolumesFrom": null,
+ "CapAdd": [],
+ "CapDrop": [
+ "CAP_AUDIT_WRITE",
+ "CAP_MKNOD",
+ "CAP_NET_RAW"
+ ],
+ "Dns": [],
+ "DnsOptions": [],
+ "DnsSearch": [],
+ "ExtraHosts": [],
+ "GroupAdd": [],
+ "IpcMode": "private",
+ "Cgroup": "",
+ "Cgroups": "default",
+ "Links": null,
+ "OomScoreAdj": 0,
+ "PidMode": "private",
+ "Privileged": false,
+ "PublishAllPorts": false,
+ "ReadonlyRootfs": false,
+ "SecurityOpt": [],
+ "Tmpfs": {},
+ "UTSMode": "private",
+ "UsernsMode": "",
+ "ShmSize": 65536000,
+ "Runtime": "oci",
+ "ConsoleSize": [
+ 0,
+ 0
+ ],
+ "Isolation": "",
+ "CpuShares": 0,
+ "Memory": 0,
+ "NanoCpus": 0,
+ "CgroupParent": "user.slice",
+ "BlkioWeight": 0,
+ "BlkioWeightDevice": null,
+ "BlkioDeviceReadBps": null,
+ "BlkioDeviceWriteBps": null,
+ "BlkioDeviceReadIOps": null,
+ "BlkioDeviceWriteIOps": null,
+ "CpuPeriod": 0,
+ "CpuQuota": 0,
+ "CpuRealtimePeriod": 0,
+ "CpuRealtimeRuntime": 0,
+ "CpusetCpus": "",
+ "CpusetMems": "",
+ "Devices": [],
+ "DiskQuota": 0,
+ "KernelMemory": 0,
+ "MemoryReservation": 0,
+ "MemorySwap": 0,
+ "MemorySwappiness": 0,
+ "OomKillDisable": false,
+ "PidsLimit": 2048,
+ "Ulimits": [],
+ "CpuCount": 0,
+ "CpuPercent": 0,
+ "IOMaximumIOps": 0,
+ "IOMaximumBandwidth": 0,
+ "CgroupConf": null
+ }
+ }
+]
+```
+
+```
+$ podman container inspect nervous_fermi --format "{{.ImageName}}"
+registry.access.redhat.com/ubi8:latest
+```
+
+```
+$ podman container inspect foobar --format "{{.GraphDriver.Name}}"
+overlay
+```
+
+```
+$ podman container inspect --latest --format {{.EffectiveCaps}}
+[CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_NET_BIND_SERVICE CAP_SETFCAP CAP_SETGID CAP_SETPCAP CAP_SETUID CAP_SYS_CHROOT]
+```
+
+## SEE ALSO
+**[podman(1)](podman.1.md)**,**[podman-container(1)](podman-container.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
+
+## HISTORY
+Sep 2021, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-container.1.md b/docs/source/markdown/podman-container.1.md
index 3cc90d9ec..c950347a9 100644
--- a/docs/source/markdown/podman-container.1.md
+++ b/docs/source/markdown/podman-container.1.md
@@ -24,7 +24,7 @@ The container command allows you to manage containers
| exists | [podman-container-exists(1)](podman-container-exists.1.md) | Check if a container exists in local storage |
| export | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
| init | [podman-init(1)](podman-init.1.md) | Initialize a container |
-| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
+| inspect | [podman-container-inspect(1)](podman-container-inspect.1.md)| Display a container's configuration. |
| kill | [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |
| list | [podman-ps(1)](podman-ps.1.md) | List the containers on the system.(alias ls) |
| logs | [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 0c48f105e..ee52bfd13 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -513,7 +513,11 @@ Not implemented
#### **--log-driver**="*k8s-file*"
-Logging driver for the container. Currently available options are *k8s-file*, *journald*, and *none*, with *json-file* aliased to *k8s-file* for scripting compatibility.
+Logging driver for the container. Currently available options are *k8s-file*, *journald*, *none* and *passthrough*, with *json-file* aliased to *k8s-file* for scripting compatibility.
+
+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
+vulnerable to attacks via TIOCSTI.
#### **--log-opt**=*name*=*value*
@@ -595,6 +599,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared
+ type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true
+
type=volume,source=vol1,destination=/path/in/container,ro=true
type=tmpfs,tmpfs-size=512M,destination=/path/in/container
@@ -613,6 +619,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· ro, readonly: true or false (default).
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
+
Options specific to image:
· rw, readwrite: true or false (default).
@@ -627,6 +635,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
. relabel: shared, private.
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
+
Options specific to tmpfs:
· ro, readonly: true or false (default).
@@ -639,6 +649,7 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· notmpcopyup: Disable copying files from the image to the tmpfs.
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
#### **--name**=*name*
@@ -682,7 +693,7 @@ Valid _mode_ values are:
#### **--network-alias**=*alias*
-Add network-scoped alias for the container
+Add network-scoped alias for the container. NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation that will be removed in a later release.
#### **--no-healthcheck**
@@ -721,7 +732,7 @@ Default is to create a private PID namespace for the container
#### **--pids-limit**=*limit*
-Tune the container's pids limit. Set `0` to have unlimited pids for the container. (default "4096" on systems that support PIDS cgroups).
+Tune the container's pids limit. Set `-1` to have unlimited pids for the container. (default "4096" on systems that support PIDS cgroups).
#### **--platform**=*OS/ARCH*
diff --git a/docs/source/markdown/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md
index 2e9f68bf3..9ae3941ec 100644
--- a/docs/source/markdown/podman-generate-kube.1.md
+++ b/docs/source/markdown/podman-generate-kube.1.md
@@ -37,8 +37,6 @@ random port is assigned by Podman in the specification.
Create Kubernetes Pod YAML for a container called `some-mariadb`.
```
$ sudo podman generate kube some-mariadb
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -93,8 +91,6 @@ status: {}
Create Kubernetes Pod YAML for a container with the directory `/home/user/my-data` on the host bind-mounted in the container to `/volume`.
```
$ podman generate kube my-container-with-bind-mounted-data
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -147,8 +143,6 @@ status: {}
Create Kubernetes Pod YAML for a container with the named volume `priceless-data` mounted in the container at `/volume`.
```
$ podman generate kube my-container-using-priceless-data
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
@@ -200,8 +194,6 @@ status: {}
Create Kubernetes Pod YAML for a pod called `demoweb` and include a service.
```
$ sudo podman generate kube -s demoweb
-# Generation of Kubernetes YAML is still under development!
-#
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
diff --git a/docs/source/markdown/podman-image-inspect.1.md b/docs/source/markdown/podman-image-inspect.1.md
new file mode 100644
index 000000000..a4f81dfc0
--- /dev/null
+++ b/docs/source/markdown/podman-image-inspect.1.md
@@ -0,0 +1,105 @@
+% podman-image-inspect(1)
+
+## NAME
+podman\-image\-inspect - Display an image's configuration
+
+## SYNOPSIS
+**podman image inspect** [*options*] *image* [*image* ...]
+
+## DESCRIPTION
+
+This displays the low-level information on images identified by name or ID. By default, this will render
+all results in a JSON array. If a format is specified, the given template will be executed for each result.
+
+## OPTIONS
+
+#### **--format**, **-f**=*format*
+
+Format the output using the given Go template.
+The keys of the returned JSON can be used as the values for the --format flag (see examples below).
+
+## EXAMPLE
+
+```
+$ podman image inspect fedora
+[
+ {
+ "Id": "37e5619f4a8ca9dbc4d6c0ae7890625674a10dbcfb76201399e2aaddb40da17d",
+ "Digest": "sha256:1b0d4ddd99b1a8c8a80e885aafe6034c95f266da44ead992aab388e6aa91611a",
+ "RepoTags": [
+ "registry.fedoraproject.org/fedora:latest"
+ ],
+ "RepoDigests": [
+ "registry.fedoraproject.org/fedora@sha256:1b0d4ddd99b1a8c8a80e885aafe6034c95f266da44ead992aab388e6aa91611a",
+ "registry.fedoraproject.org/fedora@sha256:b5290db40008aae9272ad3a6bd8070ef7ecd547c3bef014b894c327960acc582"
+ ],
+ "Parent": "",
+ "Comment": "Created by Image Factory",
+ "Created": "2021-08-09T05:48:47Z",
+ "Config": {
+ "Env": [
+ "DISTTAG=f34container",
+ "FGC=f34",
+ "container=oci"
+ ],
+ "Cmd": [
+ "/bin/bash"
+ ],
+ "Labels": {
+ "license": "MIT",
+ "name": "fedora",
+ "vendor": "Fedora Project",
+ "version": "34"
+ }
+ },
+ "Version": "1.10.1",
+ "Author": "",
+ "Architecture": "amd64",
+ "Os": "linux",
+ "Size": 183852302,
+ "VirtualSize": 183852302,
+ "GraphDriver": {
+ "Name": "overlay",
+ "Data": {
+ "UpperDir": "/home/dwalsh/.local/share/containers/storage/overlay/0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2/diff",
+ "WorkDir": "/home/dwalsh/.local/share/containers/storage/overlay/0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2/work"
+ }
+ },
+ "RootFS": {
+ "Type": "layers",
+ "Layers": [
+ "sha256:0203e243f1ca4b6bb49371ecd21363212467ec6d7d3fa9f324cd4e78cc6b5fa2"
+ ]
+ },
+ "Labels": {
+ "license": "MIT",
+ "name": "fedora",
+ "vendor": "Fedora Project",
+ "version": "34"
+ },
+ "Annotations": {},
+ "ManifestType": "application/vnd.docker.distribution.manifest.v2+json",
+ "User": "",
+ "History": [
+ {
+ "created": "2021-08-09T05:48:47Z",
+ "comment": "Created by Image Factory"
+ }
+ ],
+ "NamesHistory": [
+ "registry.fedoraproject.org/fedora:latest"
+ ]
+ }
+]
+```
+
+```
+$ podman image inspect --format '{{ .Id }}' fedora
+37e5619f4a8ca9dbc4d6c0ae7890625674a10dbcfb76201399e2aaddb40da17d
+```
+
+## SEE ALSO
+**[podman(1)](podman.1.md)**,**[podman-image(1)](podman-image.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
+
+## HISTORY
+Sep 2021, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md
index bd08d18fc..493332ec0 100644
--- a/docs/source/markdown/podman-image-prune.1.md
+++ b/docs/source/markdown/podman-image-prune.1.md
@@ -17,6 +17,10 @@ The image prune command does not prune cache images that only use layers that ar
Remove dangling images and images that have no associated containers.
+#### **--external**
+
+Remove images even when they are used by external containers (e.g., build containers).
+
#### **--filter**=*filters*
Provide filter values.
diff --git a/docs/source/markdown/podman-image.1.md b/docs/source/markdown/podman-image.1.md
index 3e6050d99..01024519f 100644
--- a/docs/source/markdown/podman-image.1.md
+++ b/docs/source/markdown/podman-image.1.md
@@ -11,30 +11,30 @@ The image command allows you to manage images
## COMMANDS
-| Command | Man Page | Description |
-| -------- | ----------------------------------------------- | --------------------------------------------------------------------------- |
-| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. |
-| diff | [podman-image-diff(1)](podman-image-diff.1.md) | Inspect changes on an image's filesystem. |
-| exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if an image exists in local storage. |
-| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. |
-| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
-| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display an image or image's configuration. |
-| list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) |
-| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. |
-| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. |
-| prune | [podman-image-prune(1)](podman-image-prune.1.md) | Remove all unused images from the local store. |
-| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
-| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
-| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
-| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. |
-| scp | [podman-image-scp(1)](podman-image-scp.1.md) | Securely copy an image from one host to another. |
-| search | [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
-| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. |
-| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
-| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. |
-| trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container registry image trust policy. |
-| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. |
-| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. |
+| Command | Man Page | Description |
+| -------- | --------------------------------------------------- | ----------------------------------------------------------------------- |
+| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. |
+| diff | [podman-image-diff(1)](podman-image-diff.1.md) | Inspect changes on an image's filesystem. |
+| exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if an image exists in local storage. |
+| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. |
+| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
+| inspect | [podman-image-inspect(1)](podman-image-inspect.1.md)| Display an image's configuration. |
+| list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) |
+| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. |
+| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. |
+| prune | [podman-image-prune(1)](podman-image-prune.1.md) | Remove all unused images from the local store. |
+| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
+| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
+| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
+| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. |
+| scp | [podman-image-scp(1)](podman-image-scp.1.md) | Securely copy an image from one host to another. |
+| search | [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
+| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. |
+| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
+| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. |
+| trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container registry image trust policy. |
+| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. |
+| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. |
## SEE ALSO
podman
diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md
index ae26c1bbb..83dc5cbbe 100644
--- a/docs/source/markdown/podman-inspect.1.md
+++ b/docs/source/markdown/podman-inspect.1.md
@@ -14,6 +14,8 @@ all results in a JSON array. If the inspect type is all, the order of inspection
If a format is specified, the given template will be executed for each result.
For more inspection options, see also
+[podman-container-inspect(1)](podman-container-inspect.1.md),
+[podman-image-inspect(1)](podman-image-inspect.1.md),
[podman-network-inspect(1)](podman-network-inspect.1.md),
[podman-pod-inspect(1)](podman-pod-inspect.1.md), and
[podman-volume-inspect(1)](podman-volume-inspect.1.md).
@@ -160,7 +162,7 @@ myNetwork
```
## SEE ALSO
-podman(1)
+**[podman(1)](podman.1.md)**,**[podman-container-inspect(1)](podman-container-inspect.1.md)**,**[podman-image-inspect(1)](podman-image-inspect.1.md)**,**[podman-network-inspect(1)](podman-network-inspect.1.md)**,**[podman-pod-inspect(1)](podman-pod-inspect.1.md)**,**[podman-volume-inspect(1)](podman-volume-inspect.1.md)**.
## HISTORY
July 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md
index c864a87ef..f1fbd56ee 100644
--- a/docs/source/markdown/podman-machine-init.1.md
+++ b/docs/source/markdown/podman-machine-init.1.md
@@ -40,13 +40,17 @@ do these things manually or handle otherwise.
#### **--image-path**
Fully qualified path or URL to the VM image.
-Can also be set to `testing` or `stable` to pull down default image.
+Can also be set to `testing`, `next`, or `stable` to pull down default image.
Defaults to `testing`.
#### **--memory**, **-m**=*number*
Memory (in MB).
+#### **--now**
+
+Start the virtual machine immediately after it has been initialized.
+
#### **--help**
Print usage statement.
diff --git a/docs/source/markdown/podman-machine-ssh.1.md b/docs/source/markdown/podman-machine-ssh.1.md
index a5cf69107..c4c732819 100644
--- a/docs/source/markdown/podman-machine-ssh.1.md
+++ b/docs/source/markdown/podman-machine-ssh.1.md
@@ -4,7 +4,7 @@
podman\-machine\-ssh - SSH into a virtual machine
## SYNOPSIS
-**podman machine ssh** [*name*] [*command* [*arg* ...]]
+**podman machine ssh** [*options*] [*name*] [*command* [*arg* ...]]
## DESCRIPTION
@@ -21,6 +21,10 @@ with the virtual machine is established.
Print usage statement.
+#### **--username**=*name*
+
+Username to use when SSH-ing into the VM.
+
## EXAMPLES
To get an interactive session with the default virtual machine:
diff --git a/docs/source/markdown/podman-network-connect.1.md b/docs/source/markdown/podman-network-connect.1.md
index 47a54bd33..39893c676 100644
--- a/docs/source/markdown/podman-network-connect.1.md
+++ b/docs/source/markdown/podman-network-connect.1.md
@@ -14,6 +14,8 @@ Once connected, the container can communicate with other containers in the same
#### **--alias**
Add network-scoped alias for the container. If the network is using the `dnsname` CNI plugin, these aliases
can be used for name resolution on the given network. Multiple *--alias* options may be specified as input.
+NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation
+that will be removed in a later release.
## EXAMPLE
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index b4c3fc2eb..fcb8ddeb9 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -38,6 +38,22 @@ Examples of the List Format:
0-4,9 # bits 0, 1, 2, 3, 4, and 9 set
0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13, and 14 set
+#### **--device**=_host-device_[**:**_container-device_][**:**_permissions_]
+
+Add a host device to the pod. Optional *permissions* parameter
+can be used to specify device permissions It is a combination of
+**r** for read, **w** for write, and **m** for **mknod**(2).
+
+Example: **--device=/dev/sdc:/dev/xvdc:rwm**.
+
+Note: if _host_device_ is a symbolic link then it will be resolved first.
+The pod will only store the major and minor numbers of the host device.
+
+Note: the pod implements devices by storing the initial configuration passed by the user and recreating the device on each container added to the pod.
+
+Podman may load kernel modules required for using the specified
+device. The devices that Podman will load modules for when necessary are:
+/dev/fuse.
#### **--dns**=*ipaddr*
@@ -141,7 +157,7 @@ Set network mode for the pod. Supported values are:
#### **--network-alias**=strings
-Add a DNS alias for the container. When the container is joined to a CNI network with support for the dnsname plugin, the container will be accessible through this name from other containers in the network.
+Add a DNS alias for the pod. When the pod is joined to a CNI network with support for the dnsname plugin, the containers inside the pod will be accessible through this name from other containers in the network.
#### **--no-hosts**
diff --git a/docs/source/markdown/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md
index 1f4e6cb06..0c58b099e 100644
--- a/docs/source/markdown/podman-pod-inspect.1.md
+++ b/docs/source/markdown/podman-pod-inspect.1.md
@@ -70,7 +70,7 @@ Valid placeholders for the Go template are listed below:
```
## SEE ALSO
-podman-pod(1), podman-pod-ps(1)
+**[podman(1)](podman.1.md)**,**[podman-pod(1)](podman-pod.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
## HISTORY
August 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md
index e34b1964b..4f3ec5541 100644
--- a/docs/source/markdown/podman-rmi.1.md
+++ b/docs/source/markdown/podman-rmi.1.md
@@ -12,6 +12,8 @@ podman\-rmi - Removes one or more locally stored images
Removes one or more locally stored images.
Passing an argument _image_ deletes it, along with any of its dangling parent images. A dangling image is an image without a tag and without being referenced by another image.
+Note: To delete an image from a remote registry, use the [**skopeo delete**](https://github.com/containers/skopeo/blob/main/docs/skopeo-delete.1.md) command. Some registries do not allow users to delete an image via a CLI remotely.
+
## OPTIONS
#### **--all**, **-a**
@@ -51,7 +53,7 @@ $ podman rmi -a -f
**125** The command fails for any other reason
## SEE ALSO
-podman(1)
+podman(1), skopeo-delete(1)
## HISTORY
March 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 7b6a56fc6..5cc17f470 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -538,7 +538,12 @@ Not implemented.
#### **--log-driver**="*driver*"
-Logging driver for the container. Currently available options are **k8s-file**, **journald**, and **none**, with **json-file** aliased to **k8s-file** for scripting compatibility.
+Logging driver for the container. Currently available options are **k8s-file**, **journald**, **none** and **passthrough**, with **json-file** aliased to **k8s-file** for scripting compatibility.
+
+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
+vulnerable to attacks via TIOCSTI.
+
#### **--log-opt**=*name*=*value*
@@ -615,6 +620,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared
+ type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true
+
type=volume,source=vol1,destination=/path/in/container,ro=true
type=tmpfs,tmpfs-size=512M,destination=/path/in/container
@@ -633,6 +640,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· ro, readonly: true or false (default).
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
+
Options specific to image:
· rw, readwrite: true or false (default).
@@ -647,6 +656,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
. relabel: shared, private.
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
+
Options specific to tmpfs:
· ro, readonly: true or false (default).
@@ -659,6 +670,8 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· notmpcopyup: Disable copying files from the image to the tmpfs.
+ . U, chown: true or false (default). Change recursively the owner and group of the source volume based on the UID and GID of the container.
+
#### **--name**=*name*
Assign a name to the container.
@@ -702,7 +715,7 @@ Valid _mode_ values are:
#### **--network-alias**=*alias*
-Add network-scoped alias for the container
+Add network-scoped alias for the container. NOTE: A container will only have access to aliases on the first network that it joins. This is a limitation that will be removed in a later release.
#### **--no-healthcheck**
@@ -743,7 +756,7 @@ The default is to create a private PID namespace for the container.
#### **--pids-limit**=*limit*
-Tune the container's pids limit. Set to **0** to have unlimited pids for the container. The default is **4096** on systems that support "pids" cgroup controller.
+Tune the container's pids limit. Set to **-1** to have unlimited pids for the container. The default is **4096** on systems that support "pids" cgroup controller.
#### **--platform**=*OS/ARCH*
diff --git a/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md
index 1f1f60b22..842bc8b41 100644
--- a/docs/source/markdown/podman-save.1.md
+++ b/docs/source/markdown/podman-save.1.md
@@ -29,6 +29,10 @@ Note: `:` is a restricted character and cannot be part of the file name.
Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source)
Note: This flag can only be set when using the **dir** transport i.e --format=oci-dir or --format=docker-dir
+#### **--uncompressed**
+
+Accept uncompressed layers when copying OCI images.
+
#### **--output**, **-o**=*file*
Write to a file, default is STDOUT
diff --git a/docs/source/markdown/podman-system-service.1.md b/docs/source/markdown/podman-system-service.1.md
index dfb026de1..3bc4fc7f1 100644
--- a/docs/source/markdown/podman-system-service.1.md
+++ b/docs/source/markdown/podman-system-service.1.md
@@ -30,6 +30,9 @@ Note: The default systemd unit files (system and user) change the log-level opti
The time until the session expires in _seconds_. The default is 5
seconds. A value of `0` means no timeout, therefore the session will not expire.
+The default timeout can be changed via the `service_timeout=VALUE` field in containers.conf.
+See **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information.
+
#### **--cors**
CORS headers to inject to the HTTP response. The default value is empty string which disables CORS headers.
@@ -46,7 +49,7 @@ podman system service --time 5
```
## SEE ALSO
-podman(1), podman-system-service(1), podman-system-connection(1)
+**[podman(1)](podman.1.md)**, **[podman-system-connection(1)](podman-system-connection.1.md)**, **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)**
## HISTORY
January 2020, Originally compiled by Brent Baude `<bbaude@redhat.com>`
diff --git a/docs/source/markdown/podman-volume-inspect.1.md b/docs/source/markdown/podman-volume-inspect.1.md
index ea0ee91b4..4595ccda6 100644
--- a/docs/source/markdown/podman-volume-inspect.1.md
+++ b/docs/source/markdown/podman-volume-inspect.1.md
@@ -40,7 +40,7 @@ $ podman volume inspect --format "{{.Driver}} {{.Scope}}" myvol
```
## SEE ALSO
-podman-volume(1)
+**[podman(1)](podman.1.md)**,**[podman-volume(1)](podman-volume.1.md)**, **[podman-inspect(1)](podman-inspect.1.md)**
## HISTORY
November 2018, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
diff --git a/go.mod b/go.mod
index a919b6dec..3c2e55f07 100644
--- a/go.mod
+++ b/go.mod
@@ -6,18 +6,18 @@ require (
github.com/BurntSushi/toml v0.4.1
github.com/blang/semver v3.5.1+incompatible
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37
- github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
+ github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2
github.com/checkpoint-restore/go-criu/v5 v5.1.0
github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9
- github.com/containernetworking/cni v0.8.1
- github.com/containernetworking/plugins v0.9.1
+ github.com/containernetworking/cni v1.0.1
+ github.com/containernetworking/plugins v1.0.1
github.com/containers/buildah v1.23.0
- github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285
+ github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.0
github.com/containers/ocicrypt v1.1.2
- github.com/containers/psgo v1.6.0
- github.com/containers/storage v1.36.0
+ github.com/containers/psgo v1.7.1
+ github.com/containers/storage v1.36.1-0.20210929132900-162a0bf730ce
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
@@ -41,6 +41,7 @@ require (
github.com/hpcloud/tail v1.0.0
github.com/json-iterator/go v1.1.12
github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/mattn/go-isatty v0.0.14
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/mrunalp/fileutils v0.5.0
github.com/onsi/ginkgo v1.16.4
@@ -61,13 +62,12 @@ require (
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/vbauerster/mpb/v6 v6.0.4
- github.com/vbauerster/mpb/v7 v7.1.4 // indirect
- github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
+ github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
- k8s.io/api v0.22.1
- k8s.io/apimachinery v0.22.1
+ k8s.io/api v0.22.2
+ k8s.io/apimachinery v0.22.2
)
diff --git a/go.sum b/go.sum
index 264247251..bee514506 100644
--- a/go.sum
+++ b/go.sum
@@ -95,6 +95,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
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/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=
@@ -121,6 +122,7 @@ github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37 h1:uxxtrnACqI9zK4ENDMf0WpXfUsHP5V8liuq5QdgDISU=
github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/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=
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=
@@ -129,8 +131,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7 h1:ZmSAEFFtv3mepC4/Ze6E/hi6vGZlhRvywqp1l+w+qqw=
-github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7/go.mod h1:Kp3ezoDVdhfYxZUtgs4OL8sVvgOLz3txk0sbQD0opvw=
+github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2 h1:z7G4H5f1Z/n3di9qnGtKDm6jmP434HD7dIEh3YyLn9I=
+github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2/go.mod h1:yvaQuauIKzvfX/PIqINxWxoOYd35Dk/U2MS8onfkRHU=
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
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=
@@ -238,16 +240,18 @@ github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1Dv
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 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI=
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
+github.com/containernetworking/cni v1.0.1 h1:9OIL/sZmMYDBe+G8svzILAlulUpaDTUjeAbtH/JNLBo=
+github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
-github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8=
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.0 h1:qGIeSNOczUHzvnaaOS29HSMiYAjw6JgIXYksAyvqnLs=
github.com/containers/buildah v1.23.0/go.mod h1:K0iMKgy/MffkkgELBXhSXwTy2HTT6hM0X8qruDR1FwU=
github.com/containers/common v0.44.0/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
-github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285 h1:sXBzh8CcqR5cGGY9cM/AUIk58CJKHbyljVtFh8HYyLY=
-github.com/containers/common v0.44.1-0.20210914173811-fcaa2e0de285/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
+github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6 h1:DojkCc4a9f3WB25Fk0GDap1/OkKU9UmDLvPJyqw3TBc=
+github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6/go.mod h1:L4+sJlqi+R7frlbiWBW0baPra/cH8u5ZYwbxkukw3Lk=
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.16.0 h1:WQcNSzb7+ngS2cfynx0vUwhk+scpgiKlldVcsF8GPbI=
@@ -259,17 +263,19 @@ 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.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk=
-github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8=
+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/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0oznMLzzRDQ8s20=
-github.com/containers/storage v1.36.0 h1:OelxllCW19tnNngYuZw2ty/zLabVMG5rSs3KSwO1Lzc=
github.com/containers/storage v1.36.0/go.mod h1:vbd3SKVQNHdmU5qQI6hTEcKPxnZkGqydG4f6uwrI5a8=
+github.com/containers/storage v1.36.1-0.20210929132900-162a0bf730ce h1:6YOfANEWtL7+Q4RmnAfloGLIJNtt17MEHjvlHXz0vVY=
+github.com/containers/storage v1.36.1-0.20210929132900-162a0bf730ce/go.mod h1:b7OGxODIyB3XpvCSWR91lllT9fv9DXeC8yfnaUocWJU=
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/etcd v3.3.13+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-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
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=
@@ -555,6 +561,7 @@ github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294/go.mod h1:TKl4jN
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5yokbMBpVLZQxo43wCZxRwl00mX+dd44=
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.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -584,8 +591,9 @@ github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
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.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
-github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4=
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/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=
@@ -617,8 +625,9 @@ github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
@@ -652,8 +661,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
+github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
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/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
@@ -703,8 +713,8 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
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/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
-github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
@@ -713,7 +723,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
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.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
+github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -818,7 +828,9 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
+github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
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=
@@ -909,12 +921,14 @@ github.com/vbauerster/mpb/v7 v7.1.4 h1:XGWpWEB8aWnvqSlAMA7F7kdeUGqcTujuVFvYj9+59
github.com/vbauerster/mpb/v7 v7.1.4/go.mod h1:4zulrZfvshMOnd2APiHgWS9Yrw08AzZVRr9G11tkpcQ=
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 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=
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/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 h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
+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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -1444,13 +1458,13 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
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/api v0.22.1 h1:ISu3tD/jRhYfSW8jI/Q1e+lRxkR7w9UwQEZ7FgslrwY=
-k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY=
+k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw=
+k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
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/apimachinery v0.22.1 h1:DTARnyzmdHMz7bFWFDDm22AM4pLWTQECMpRTFu2d2OM=
-k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
+k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk=
+k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
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=
diff --git a/hack/get_release_info.sh b/hack/get_release_info.sh
deleted file mode 100755
index e1020e677..000000000
--- a/hack/get_release_info.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env bash
-
-# This script produces various bits of metadata needed by Makefile. Using
-# a script allows uniform behavior across multiple environments and
-# distributions. The script expects a single argument, as reflected below.
-
-set -euo pipefail
-
-cd "${GOSRC:-$(dirname $0)/../}"
-
-valid_args() {
- REGEX='^\s+[[:upper:]]+\*[)]'
- egrep --text --no-filename --group-separator=' ' --only-matching "$REGEX" "$0" | \
- cut -d '*' -f 1
-}
-
-# `git describe` will never produce a useful version number under all
-# branches. This is because the podman release process (see `RELEASE_PROCESS.md`)
-# tags release versions only on release-branches (i.e. never on main).
-# Scraping the version number directly from the source, is the only way
-# to reliably obtain the number from all the various contexts supported by
-# the `Makefile`.
-scrape_version() {
- local v
- # extract the value of 'var Version'
- v=$(sed -ne 's/^var\s\+Version\s\+=\s.*("\(.*\)").*/\1/p' <version/version.go)
- # If it's empty, something has changed in version.go, that would be bad!
- test -n "$v"
- # Value consumed literally, must not have any embedded newlines
- echo -n "$v"
-}
-
-unset OUTPUT
-case "$1" in
- # Wild-card suffix needed by valid_args() e.g. possible bad grep of "$(echo $FOO)"
- VERSION*)
- OUTPUT="${CIRRUS_TAG:-$(scrape_version)}"
- ;;
- NUMBER*)
- OUTPUT="$($0 VERSION | sed 's/-.*//')"
- ;;
- DIST_VER*)
- OUTPUT="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
- ;;
- DIST*)
- OUTPUT="$(source /etc/os-release; echo $ID)"
- ;;
- ARCH*)
- OUTPUT="${GOARCH:-$(go env GOARCH 2> /dev/null)}"
- ;;
- BASENAME*)
- OUTPUT="podman"
- ;;
- REMOTENAME*)
- OUTPUT="$($0 BASENAME)-remote"
- ;;
- *)
- echo "Error, unknown/unsupported argument '$1', valid arguments:"
- valid_args
- exit 1
- ;;
-esac
-
-if [[ -n "$OUTPUT" ]]
-then
- echo -n "$OUTPUT"
-else
- echo "Error, empty output for info: '$1'" > /dev/stderr
- exit 2
-fi
diff --git a/hack/podman-registry-go/registry.go b/hack/podman-registry-go/registry.go
index e9ec61ffe..92e3008f3 100644
--- a/hack/podman-registry-go/registry.go
+++ b/hack/podman-registry-go/registry.go
@@ -61,7 +61,7 @@ func Start() (*Registry, error) {
case portKey:
registry.Port = val
default:
- logrus.Errorf("unexpected podman-registry output: %q", s)
+ logrus.Errorf("Unexpected podman-registry output: %q", s)
}
}
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 56b4bafd3..1242a8d6b 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -954,7 +954,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) {
// not worth erroring over.
// If we do, a single bad container JSON
// could render libpod unusable.
- logrus.Errorf("Error retrieving container %s from the database: %v", string(id), err)
+ logrus.Errorf("Retrieving container %s from the database: %v", string(id), err)
}
} else {
ctrs = append(ctrs, ctr)
@@ -1756,6 +1756,23 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
if err := allCtrsBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
return errors.Wrapf(err, "error renaming container %s in all containers bucket in DB", ctr.ID())
}
+ if ctr.config.Pod != "" {
+ podsBkt, err := getPodBucket(tx)
+ if err != nil {
+ return err
+ }
+ podBkt := podsBkt.Bucket([]byte(ctr.config.Pod))
+ if podBkt == nil {
+ return errors.Wrapf(define.ErrInternal, "bucket for pod %s does not exist", ctr.config.Pod)
+ }
+ podCtrBkt := podBkt.Bucket(containersBkt)
+ if podCtrBkt == nil {
+ return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", ctr.config.Pod)
+ }
+ if err := podCtrBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
+ return errors.Wrapf(err, "error renaming container %s in pod %s members bucket", ctr.ID(), ctr.config.Pod)
+ }
+ }
}
}
@@ -2556,7 +2573,7 @@ func (s *BoltState) AllVolumes() ([]*Volume, error) {
if err := s.getVolumeFromDB(id, volume, volBucket); err != nil {
if errors.Cause(err) != define.ErrNSMismatch {
- logrus.Errorf("Error retrieving volume %s from the database: %v", string(id), err)
+ logrus.Errorf("Retrieving volume %s from the database: %v", string(id), err)
}
} else {
volumes = append(volumes, volume)
@@ -3352,7 +3369,7 @@ func (s *BoltState) AllPods() ([]*Pod, error) {
if err := s.getPodFromDB(id, pod, podBucket); err != nil {
if errors.Cause(err) != define.ErrNSMismatch {
- logrus.Errorf("Error retrieving pod %s from the database: %v", string(id), err)
+ logrus.Errorf("Retrieving pod %s from the database: %v", string(id), err)
}
} else {
pods = append(pods, pod)
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index f63876c14..3e3c17a9e 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -259,7 +259,7 @@ func (s *BoltState) getDBCon() (*bolt.DB, error) {
// of a defer statement only
func (s *BoltState) deferredCloseDBCon(db *bolt.DB) {
if err := s.closeDBCon(db); err != nil {
- logrus.Errorf("failed to close libpod db: %q", err)
+ logrus.Errorf("Failed to close libpod db: %q", err)
}
}
@@ -875,7 +875,7 @@ func (s *BoltState) removeContainer(ctr *Container, pod *Pod, tx *bolt.Tx) error
podCtrs := podDB.Bucket(containersBkt)
if podCtrs == nil {
// Malformed pod
- logrus.Errorf("pod %s malformed in database, missing containers bucket!", pod.ID())
+ logrus.Errorf("Pod %s malformed in database, missing containers bucket!", pod.ID())
} else {
ctrInPod := podCtrs.Get(ctrID)
if ctrInPod == nil {
diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go
index 72243dcc5..4fb3236a0 100644
--- a/libpod/boltdb_state_linux.go
+++ b/libpod/boltdb_state_linux.go
@@ -31,7 +31,7 @@ func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) er
return errors.Wrapf(err, "error joining network namespace of container %s", ctr.ID())
}
- logrus.Errorf("error joining network namespace for container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Joining network namespace for container %s: %v", ctr.ID(), err)
ctr.state.NetNS = nil
}
}
diff --git a/libpod/boltdb_state_unsupported.go b/libpod/boltdb_state_unsupported.go
deleted file mode 100644
index 244dc51a0..000000000
--- a/libpod/boltdb_state_unsupported.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !linux
-
-package libpod
-
-// replaceNetNS is exclusive to the Linux platform and is a no-op elsewhere
-func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error {
- return nil
-}
-
-// getNetNSPath is exclusive to the Linux platform and is a no-op elsewhere
-func getNetNSPath(ctr *Container) string {
- return ""
-}
diff --git a/libpod/container.go b/libpod/container.go
index cf727926c..4d15c04c5 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -8,7 +8,7 @@ import (
"os"
"time"
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containers/common/pkg/secrets"
"github.com/containers/image/v5/manifest"
"github.com/containers/podman/v3/libpod/define"
@@ -176,7 +176,7 @@ type ContainerState struct {
// active.
// These are DEPRECATED and will be removed in a future release.
// This field is only used for backwarts compatibility.
- NetworkStatusOld []*cnitypes.Result `json:"networkResults,omitempty"`
+ NetworkStatusOld []*types040.Result `json:"networkResults,omitempty"`
// NetworkStatus contains the network Status for all networks
// the container is attached to. Only populated if we created a network
// namespace for the container, and the network namespace is currently
@@ -278,6 +278,11 @@ func (c *Container) Config() *ContainerConfig {
return returnConfig
}
+// DeviceHostSrc returns the user supplied device to be passed down in the pod
+func (c *Container) DeviceHostSrc() []spec.LinuxDevice {
+ return c.config.DeviceHostSrc
+}
+
// Runtime returns the container's Runtime.
func (c *Container) Runtime() *Runtime {
return c.runtime
@@ -769,9 +774,9 @@ func (c *Container) ExecSessions() ([]string, error) {
return ids, nil
}
-// ExecSession retrieves detailed information on a single active exec session in
-// a container
-func (c *Container) ExecSession(id string) (*ExecSession, error) {
+// execSessionNoCopy returns the associated exec session to id.
+// Note that the session is not a deep copy.
+func (c *Container) execSessionNoCopy(id string) (*ExecSession, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
@@ -786,6 +791,17 @@ func (c *Container) ExecSession(id string) (*ExecSession, error) {
return nil, errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found in container %s", id, c.ID())
}
+ return session, nil
+}
+
+// ExecSession retrieves detailed information on a single active exec session in
+// a container
+func (c *Container) ExecSession(id string) (*ExecSession, error) {
+ session, err := c.execSessionNoCopy(id)
+ if err != nil {
+ return nil, err
+ }
+
returnSession := new(ExecSession)
if err := JSONDeepCopy(session, returnSession); err != nil {
return nil, errors.Wrapf(err, "error copying contents of container %s exec session %s", c.ID(), session.ID())
@@ -1090,7 +1106,7 @@ func (c *Container) AutoRemove() bool {
if spec.Annotations == nil {
return false
}
- return c.Spec().Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue
+ return spec.Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue
}
// Timezone returns the timezone configured inside the container.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 637f5b686..50be0eea4 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -53,7 +53,7 @@ func (c *Container) Init(ctx context.Context, recursive bool) error {
if err := c.prepare(); err != nil {
if err2 := c.cleanup(ctx); err2 != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err2)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err2)
}
return err
}
@@ -229,6 +229,10 @@ func (c *Container) Kill(signal uint) error {
// This function returns when the attach finishes. It does not hold the lock for
// the duration of its runtime, only using it at the beginning to verify state.
func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize) error {
+ switch c.LogDriver() {
+ case define.PassthroughLogging:
+ return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot attach")
+ }
if !c.batched {
c.lock.Lock()
if err := c.syncContainer(); err != nil {
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index 87e5d511c..6ae225cbc 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -51,7 +51,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
}
defer func() {
if err := c.unpause(); err != nil {
- logrus.Errorf("error unpausing container %q: %v", c.ID(), err)
+ logrus.Errorf("Unpausing container %q: %v", c.ID(), err)
}
}()
}
diff --git a/libpod/container_config.go b/libpod/container_config.go
index 0374c25fe..54d102a71 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -381,6 +381,8 @@ type ContainerMiscConfig struct {
PidFile string `json:"pid_file,omitempty"`
// CDIDevices contains devices that use the CDI
CDIDevices []string `json:"cdiDevices,omitempty"`
+ // DeviceHostSrc contains the original source on the host
+ DeviceHostSrc []spec.LinuxDevice `json:"device_host_src,omitempty"`
// EnvSecrets are secrets that are set as environment variables
EnvSecrets map[string]*secrets.Secret `json:"secret_env,omitempty"`
// InitContainerType specifies if the container is an initcontainer
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go
index a35824289..7d4dd0d46 100644
--- a/libpod/container_copy_linux.go
+++ b/libpod/container_copy_linux.go
@@ -174,7 +174,7 @@ func (c *Container) copyToArchive(ctx context.Context, path string, writer io.Wr
// getContainerUser returns the specs.User and ID mappings of the container.
func getContainerUser(container *Container, mountPoint string) (specs.User, error) {
- userspec := container.Config().User
+ userspec := container.config.User
uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
u := specs.User{
diff --git a/libpod/container_copy_unsupported.go b/libpod/container_copy_unsupported.go
deleted file mode 100644
index b2bdd3e3d..000000000
--- a/libpod/container_copy_unsupported.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
- "io"
-)
-
-func (c *Container) copyFromArchive(ctx context.Context, path string, reader io.Reader) (func() error, error) {
- return nil, nil
-}
-
-func (c *Container) copyToArchive(ctx context.Context, path string, writer io.Writer) (func() error, error) {
- return nil, nil
-}
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 5d4bcb422..f99fb7d3f 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -415,7 +415,7 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w
session.ExitCode = define.ExecErrorCodeGeneric
if err := c.save(); err != nil {
- logrus.Errorf("Error saving container %s exec session %s after failure to prepare: %v", err, c.ID(), session.ID())
+ logrus.Errorf("Saving container %s exec session %s after failure to prepare: %v", err, c.ID(), session.ID())
}
return err
@@ -440,7 +440,7 @@ func (c *Container) ExecHTTPStartAndAttach(sessionID string, r *http.Request, w
session.ExitCode = define.TranslateExecErrorToExitCode(define.ExecErrorCodeGeneric, err)
if err := c.save(); err != nil {
- logrus.Errorf("Error saving container %s exec session %s after failure to start: %v", err, c.ID(), session.ID())
+ logrus.Errorf("Saving container %s exec session %s after failure to start: %v", err, c.ID(), session.ID())
}
return err
@@ -549,7 +549,7 @@ func (c *Container) ExecStop(sessionID string, timeout *uint) error {
if err := c.cleanupExecBundle(session.ID()); err != nil {
if cleanupErr != nil {
- logrus.Errorf("Error stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr)
+ logrus.Errorf("Stopping container %s exec session %s: %v", c.ID(), session.ID(), cleanupErr)
}
cleanupErr = err
}
@@ -695,7 +695,7 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er
session.State = define.ExecStateStopped
if err := c.save(); err != nil {
- logrus.Errorf("Error saving state of container %s: %v", c.ID(), err)
+ logrus.Errorf("Saving state of container %s: %v", c.ID(), err)
}
return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it has stopped", c.ID(), session.ID())
@@ -747,7 +747,7 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
return -1, err
}
- session, err := c.ExecSession(sessionID)
+ session, err := c.execSessionNoCopy(sessionID)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchExecSession {
// TODO: If a proper Context is ever plumbed in here, we
@@ -825,7 +825,7 @@ func (c *Container) createExecBundle(sessionID string) (retErr error) {
defer func() {
if retErr != nil {
if err := os.RemoveAll(bundlePath); err != nil {
- logrus.Warnf("error removing exec bundle after creation caused another error: %v", err)
+ logrus.Warnf("Error removing exec bundle after creation caused another error: %v", err)
}
}
}()
@@ -911,7 +911,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) {
alive, err := c.ociRuntime.ExecUpdateStatus(c, id)
if err != nil {
if lastErr != nil {
- logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
continue
@@ -926,7 +926,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) {
exitCode, err := c.readExecExitCode(session.ID())
if err != nil {
if lastErr != nil {
- logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
}
@@ -940,7 +940,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) {
}
if err := c.cleanupExecBundle(id); err != nil {
if lastErr != nil {
- logrus.Errorf("Error checking container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Checking container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
}
@@ -951,7 +951,7 @@ func (c *Container) getActiveExecSessions() ([]string, error) {
if needSave {
if err := c.save(); err != nil {
if lastErr != nil {
- logrus.Errorf("Error reaping exec sessions for container %s: %v", c.ID(), lastErr)
+ logrus.Errorf("Reaping exec sessions for container %s: %v", c.ID(), lastErr)
}
lastErr = err
}
@@ -970,7 +970,7 @@ func (c *Container) removeAllExecSessions() error {
for _, id := range knownSessions {
if err := c.ociRuntime.ExecStopContainer(c, id, c.StopTimeout()); err != nil {
if lastErr != nil {
- logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
continue
@@ -978,7 +978,7 @@ func (c *Container) removeAllExecSessions() error {
if err := c.cleanupExecBundle(id); err != nil {
if lastErr != nil {
- logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
}
@@ -987,7 +987,7 @@ func (c *Container) removeAllExecSessions() error {
if err := c.runtime.state.RemoveContainerExecSessions(c); err != nil {
if errors.Cause(err) != define.ErrCtrRemoved {
if lastErr != nil {
- logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
}
@@ -997,7 +997,7 @@ func (c *Container) removeAllExecSessions() error {
if err := c.save(); err != nil {
if errors.Cause(err) != define.ErrCtrRemoved {
if lastErr != nil {
- logrus.Errorf("Error stopping container %s exec sessions: %v", c.ID(), lastErr)
+ logrus.Errorf("Stopping container %s exec sessions: %v", c.ID(), lastErr)
}
lastErr = err
}
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 530160b2d..ab79d82d9 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -151,12 +151,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
if c.config.HealthCheckConfig != nil {
// This container has a healthcheck defined in it; we need to add it's state
- healthCheckState, err := c.GetHealthCheckLog()
+ healthCheckState, err := c.getHealthCheckLog()
if err != nil {
// An error here is not considered fatal; no health state will be displayed
logrus.Error(err)
} else {
- data.State.Healthcheck = healthCheckState
+ data.State.Health = healthCheckState
}
}
@@ -178,13 +178,13 @@ func (c *Container) getContainerInspectData(size bool, driverData *define.Driver
if size {
rootFsSize, err := c.rootFsSize()
if err != nil {
- logrus.Errorf("error getting rootfs size %q: %v", config.ID, err)
+ logrus.Errorf("Getting rootfs size %q: %v", config.ID, err)
}
data.SizeRootFs = rootFsSize
rwSize, err := c.rwSize()
if err != nil {
- logrus.Errorf("error getting rw size %q: %v", config.ID, err)
+ logrus.Errorf("Getting rw size %q: %v", config.ID, err)
}
data.SizeRw = &rwSize
}
@@ -819,27 +819,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named
// Devices
// Do not include if privileged - assumed that all devices will be
// included.
- hostConfig.Devices = []define.InspectDevice{}
- if ctrSpec.Linux != nil && !hostConfig.Privileged {
- for _, dev := range ctrSpec.Linux.Devices {
- key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
- if deviceNodes == nil {
- nodes, err := util.FindDeviceNodes()
- if err != nil {
- return nil, err
- }
- deviceNodes = nodes
- }
- path, ok := deviceNodes[key]
- if !ok {
- logrus.Warnf("Could not locate device %s on host", key)
- continue
- }
- newDev := define.InspectDevice{}
- newDev.PathOnHost = path
- newDev.PathInContainer = dev.Path
- hostConfig.Devices = append(hostConfig.Devices, newDev)
- }
+ var err error
+ hostConfig.Devices, err = c.GetDevices(*&hostConfig.Privileged, *ctrSpec, deviceNodes)
+ if err != nil {
+ return nil, err
}
// Ulimits
@@ -885,3 +868,29 @@ func (c *Container) inHostPidNS() (bool, error) {
}
return true, nil
}
+
+func (c *Container) GetDevices(priv bool, ctrSpec spec.Spec, deviceNodes map[string]string) ([]define.InspectDevice, error) {
+ devices := []define.InspectDevice{}
+ if ctrSpec.Linux != nil && !priv {
+ for _, dev := range ctrSpec.Linux.Devices {
+ key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor)
+ if deviceNodes == nil {
+ nodes, err := util.FindDeviceNodes()
+ if err != nil {
+ return nil, err
+ }
+ deviceNodes = nodes
+ }
+ path, ok := deviceNodes[key]
+ if !ok {
+ logrus.Warnf("Could not locate device %s on host", key)
+ continue
+ }
+ newDev := define.InspectDevice{}
+ newDev.PathOnHost = path
+ newDev.PathInContainer = dev.Path
+ devices = append(devices, newDev)
+ }
+ }
+ return devices, nil
+}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 9ac2cd5bd..3f9738411 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -176,7 +176,7 @@ func (c *Container) waitForExitFileAndSync() error {
c.state.State = define.ContainerStateStopped
if err2 := c.save(); err2 != nil {
- logrus.Errorf("Error saving container %s state: %v", c.ID(), err2)
+ logrus.Errorf("Saving container %s state: %v", c.ID(), err2)
}
return err
@@ -278,7 +278,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err
defer func() {
if retErr != nil {
if err := c.cleanup(ctx); err != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err)
}
}
}()
@@ -709,7 +709,7 @@ func (c *Container) export(path string) error {
mountPoint = containerMount
defer func() {
if _, err := c.runtime.store.Unmount(c.ID(), false); err != nil {
- logrus.Errorf("error unmounting container %q: %v", c.ID(), err)
+ logrus.Errorf("Unmounting container %q: %v", c.ID(), err)
}
}()
}
@@ -778,7 +778,7 @@ func (c *Container) prepareToStart(ctx context.Context, recursive bool) (retErr
defer func() {
if retErr != nil {
if err := c.cleanup(ctx); err != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err)
}
}
}()
@@ -859,7 +859,7 @@ func (c *Container) startDependencies(ctx context.Context) error {
}
if len(ctrErrors) > 0 {
- logrus.Errorf("error starting some container dependencies")
+ logrus.Errorf("Starting some container dependencies")
for _, e := range ctrErrors {
logrus.Errorf("%q", e)
}
@@ -923,12 +923,11 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
// Check the status
- conf := depCtr.Config()
state, err := depCtr.State()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID())
}
- if state != define.ContainerStateRunning && !conf.IsInfra {
+ if state != define.ContainerStateRunning && !depCtr.config.IsInfra {
notRunning = append(notRunning, dep)
}
depCtrs[dep] = depCtr
@@ -1003,7 +1002,7 @@ func (c *Container) cniHosts() string {
for _, status := range c.getNetworkStatus() {
for _, netInt := range status.Interfaces {
for _, netAddress := range netInt.Networks {
- hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.Config().Name)
+ hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.config.Name)
}
}
}
@@ -1047,7 +1046,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
// upstream in any OCI runtime.
// TODO: Remove once runc supports cgroupsv2
if strings.Contains(err.Error(), "this version of runc doesn't work on cgroups v2") {
- logrus.Errorf("oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.Name())
+ logrus.Errorf("Oci runtime %q does not support CGroups V2: use system migrate to mitigate", c.ociRuntime.Name())
}
return err
}
@@ -1057,7 +1056,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error {
// Remove any exec sessions leftover from a potential prior run.
if len(c.state.ExecSessions) > 0 {
if err := c.runtime.state.RemoveContainerExecSessions(c); err != nil {
- logrus.Errorf("Error removing container %s exec sessions from DB: %v", c.ID(), err)
+ logrus.Errorf("Removing container %s exec sessions from DB: %v", c.ID(), err)
}
c.state.ExecSessions = make(map[string]*ExecSession)
}
@@ -1164,7 +1163,7 @@ func (c *Container) initAndStart(ctx context.Context) (retErr error) {
defer func() {
if retErr != nil {
if err := c.cleanup(ctx); err != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err)
}
}
}()
@@ -1211,7 +1210,7 @@ func (c *Container) start() error {
payload += daemon.SdNotifyReady
}
if sent, err := daemon.SdNotify(false, payload); err != nil {
- logrus.Errorf("Error notifying systemd of Conmon PID: %s", err.Error())
+ logrus.Errorf("Notifying systemd of Conmon PID: %s", err.Error())
} else if sent {
logrus.Debugf("Notify sent successfully")
}
@@ -1290,7 +1289,7 @@ func (c *Container) stop(timeout uint) error {
return stopErr
default:
if stopErr != nil {
- logrus.Errorf("Error syncing container %s status: %v", c.ID(), err)
+ logrus.Errorf("Syncing container %s status: %v", c.ID(), err)
return stopErr
}
return err
@@ -1328,7 +1327,7 @@ func (c *Container) stop(timeout uint) error {
c.state.FinishedTime = time.Now()
c.state.State = define.ContainerStateStopped
if err := c.save(); err != nil {
- logrus.Errorf("Error saving container %s status: %v", c.ID(), err)
+ logrus.Errorf("Saving container %s status: %v", c.ID(), err)
}
return errors.Wrapf(define.ErrConmonDead, "container %s conmon process missing, cannot retrieve exit code", c.ID())
@@ -1432,7 +1431,7 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (retEr
defer func() {
if retErr != nil {
if err := c.cleanup(ctx); err != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err)
}
}
}()
@@ -1483,7 +1482,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
defer func() {
if deferredErr != nil {
if err := c.unmountSHM(c.config.ShmDir); err != nil {
- logrus.Errorf("Error unmounting SHM for container %s after mount error: %v", c.ID(), err)
+ logrus.Errorf("Unmounting SHM for container %s after mount error: %v", c.ID(), err)
}
}
}()
@@ -1526,7 +1525,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
defer func() {
if deferredErr != nil {
if err := c.unmount(false); err != nil {
- logrus.Errorf("Error unmounting container %s after mount error: %v", c.ID(), err)
+ logrus.Errorf("Unmounting container %s after mount error: %v", c.ID(), err)
}
}
}()
@@ -1554,7 +1553,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) {
}
vol.lock.Lock()
if err := vol.unmount(false); err != nil {
- logrus.Errorf("Error unmounting volume %s after error mounting container %s: %v", vol.Name(), c.ID(), err)
+ logrus.Errorf("Unmounting volume %s after error mounting container %s: %v", vol.Name(), c.ID(), err)
}
vol.lock.Unlock()
}()
@@ -1669,7 +1668,7 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
if err := copier.Put(volMount, "", copyOpts, reader); err != nil {
err2 := <-errChan
if err2 != nil {
- logrus.Errorf("Error streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2)
+ logrus.Errorf("Streaming contents of container %s directory for volume copy-up: %v", c.ID(), err2)
}
return nil, errors.Wrapf(err, "error copying up to volume %s", vol.Name())
}
@@ -1705,7 +1704,7 @@ func (c *Container) cleanupStorage() error {
for _, containerMount := range c.config.Mounts {
if err := c.unmountSHM(containerMount); err != nil {
if cleanupErr != nil {
- logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr)
+ logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr)
}
cleanupErr = err
}
@@ -1730,7 +1729,7 @@ func (c *Container) cleanupStorage() error {
logrus.Errorf("Storage for container %s has been removed", c.ID())
} else {
if cleanupErr != nil {
- logrus.Errorf("Error cleaning up container %s storage: %v", c.ID(), cleanupErr)
+ logrus.Errorf("Cleaning up container %s storage: %v", c.ID(), cleanupErr)
}
cleanupErr = err
}
@@ -1741,7 +1740,7 @@ func (c *Container) cleanupStorage() error {
vol, err := c.runtime.state.Volume(v.Name)
if err != nil {
if cleanupErr != nil {
- logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr)
+ logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr)
}
cleanupErr = errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID())
@@ -1754,7 +1753,7 @@ func (c *Container) cleanupStorage() error {
vol.lock.Lock()
if err := vol.unmount(false); err != nil {
if cleanupErr != nil {
- logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr)
+ logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr)
}
cleanupErr = errors.Wrapf(err, "error unmounting volume %s for container %s", vol.Name(), c.ID())
}
@@ -1768,7 +1767,7 @@ func (c *Container) cleanupStorage() error {
if c.valid {
if err := c.save(); err != nil {
if cleanupErr != nil {
- logrus.Errorf("Error unmounting container %s: %v", c.ID(), cleanupErr)
+ logrus.Errorf("Unmounting container %s: %v", c.ID(), cleanupErr)
}
cleanupErr = err
}
@@ -1785,7 +1784,7 @@ func (c *Container) cleanup(ctx context.Context) error {
// Remove healthcheck unit/timer file if it execs
if c.config.HealthCheckConfig != nil {
if err := c.removeTimer(); err != nil {
- logrus.Errorf("Error removing timer for container %s healthcheck: %v", c.ID(), err)
+ logrus.Errorf("Removing timer for container %s healthcheck: %v", c.ID(), err)
}
}
@@ -1800,7 +1799,7 @@ func (c *Container) cleanup(ctx context.Context) error {
// exists.
if err := c.cleanupRuntime(ctx); err != nil {
if lastError != nil {
- logrus.Errorf("Error removing container %s from OCI runtime: %v", c.ID(), err)
+ logrus.Errorf("Removing container %s from OCI runtime: %v", c.ID(), err)
} else {
lastError = err
}
@@ -1809,7 +1808,7 @@ func (c *Container) cleanup(ctx context.Context) error {
// Unmount storage
if err := c.cleanupStorage(); err != nil {
if lastError != nil {
- logrus.Errorf("Error unmounting container %s storage: %v", c.ID(), err)
+ logrus.Errorf("Unmounting container %s storage: %v", c.ID(), err)
} else {
lastError = errors.Wrapf(err, "error unmounting container %s storage", c.ID())
}
@@ -1823,14 +1822,14 @@ func (c *Container) cleanup(ctx context.Context) error {
lastError = err
continue
}
- logrus.Errorf("error unmounting image volume %q:%q :%v", v.Source, v.Dest, err)
+ logrus.Errorf("Unmounting image volume %q:%q :%v", v.Source, v.Dest, err)
}
if err := img.Unmount(false); err != nil {
if lastError == nil {
lastError = err
continue
}
- logrus.Errorf("error unmounting image volume %q:%q :%v", v.Source, v.Dest, err)
+ logrus.Errorf("Unmounting image volume %q:%q :%v", v.Source, v.Dest, err)
}
}
@@ -1874,7 +1873,7 @@ func (c *Container) postDeleteHooks(ctx context.Context) error {
var stderr, stdout bytes.Buffer
hookErr, err := exec.Run(ctx, &hook, state, &stdout, &stderr, exec.DefaultPostKillTimeout)
if err != nil {
- logrus.Warnf("container %s: poststop hook %d: %v", c.ID(), i, err)
+ logrus.Warnf("Container %s: poststop hook %d: %v", c.ID(), i, err)
if hookErr != err {
logrus.Debugf("container %s: poststop hook %d (hook error): %v", c.ID(), i, hookErr)
}
@@ -2005,12 +2004,12 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s
}
return nil, err
}
- ociHooks, err := manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0)
+ ociHooks, err := manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0)
if err != nil {
return nil, err
}
if len(ociHooks) > 0 || config.Hooks != nil {
- logrus.Warnf("implicit hook directories are deprecated; set --ociHooks-dir=%q explicitly to continue to load ociHooks from this directory", hDir)
+ logrus.Warnf("Implicit hook directories are deprecated; set --ociHooks-dir=%q explicitly to continue to load ociHooks from this directory", hDir)
}
for i, hook := range ociHooks {
allHooks[i] = hook
@@ -2022,7 +2021,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s
return nil, err
}
- allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0)
+ allHooks, err = manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0)
if err != nil {
return nil, err
}
@@ -2030,7 +2029,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s
hookErr, err := exec.RuntimeConfigFilter(ctx, allHooks["precreate"], config, exec.DefaultPostKillTimeout)
if err != nil {
- logrus.Warnf("container %s: precreate hook: %v", c.ID(), err)
+ logrus.Warnf("Container %s: precreate hook: %v", c.ID(), err)
if hookErr != nil && hookErr != err {
logrus.Debugf("container %s: precreate hook (hook error): %v", c.ID(), hookErr)
}
@@ -2106,7 +2105,7 @@ func (c *Container) canWithPrevious() error {
// JSON files for later export
func (c *Container) prepareCheckpointExport() error {
// save live config
- if _, err := metadata.WriteJSONFile(c.Config(), c.bundlePath(), metadata.ConfigDumpFile); err != nil {
+ if _, err := metadata.WriteJSONFile(c.config, c.bundlePath(), metadata.ConfigDumpFile); err != nil {
return err
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 6ebbfd1f3..867ecc2ad 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -70,7 +70,7 @@ func (c *Container) unmountSHM(mount string) error {
return errors.Wrapf(err, "error unmounting container %s SHM mount %s", c.ID(), mount)
}
// If it's just an EINVAL or ENOENT, debug logs only
- logrus.Debugf("container %s failed to unmount %s : %v", c.ID(), mount, err)
+ logrus.Debugf("Container %s failed to unmount %s : %v", c.ID(), mount, err)
}
return nil
}
@@ -143,7 +143,7 @@ func (c *Container) prepare() error {
}
if mountStorageErr != nil {
if createErr != nil {
- logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr)
+ logrus.Errorf("Preparing container %s: %v", c.ID(), createErr)
}
createErr = mountStorageErr
}
@@ -154,7 +154,7 @@ func (c *Container) prepare() error {
if err := c.cleanupStorage(); err != nil {
// createErr is guaranteed non-nil, so print
// unconditionally
- logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr)
+ logrus.Errorf("Preparing container %s: %v", c.ID(), createErr)
createErr = errors.Wrapf(err, "error unmounting storage for container %s after network create failure", c.ID())
}
}
@@ -163,7 +163,7 @@ func (c *Container) prepare() error {
// isn't ready it will do nothing.
if createErr != nil {
if err := c.cleanupNetwork(); err != nil {
- logrus.Errorf("Error preparing container %s: %v", c.ID(), createErr)
+ logrus.Errorf("Preparing container %s: %v", c.ID(), createErr)
createErr = errors.Wrapf(err, "error cleaning up container %s network after setup failure", c.ID())
}
}
@@ -258,7 +258,7 @@ func (c *Container) cleanupNetwork() error {
// Stop the container's network namespace (if it has one)
if err := c.runtime.teardownNetNS(c); err != nil {
- logrus.Errorf("unable to cleanup network for container %s: %q", c.ID(), err)
+ logrus.Errorf("Unable to cleanup network for container %s: %q", c.ID(), err)
}
c.state.NetNS = nil
@@ -369,13 +369,46 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, err
}
- volMount := spec.Mount{
- Type: "bind",
- Source: mountPoint,
- Destination: namedVol.Dest,
- Options: namedVol.Options,
+
+ overlayFlag := false
+ for _, o := range namedVol.Options {
+ if o == "O" {
+ overlayFlag = true
+ }
+ }
+
+ if overlayFlag {
+ 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 err != nil {
+ return nil, errors.Wrapf(err, "mounting overlay failed %q", mountPoint)
+ }
+
+ for _, o := range namedVol.Options {
+ switch o {
+ case "U":
+ if err := chown.ChangeHostPathOwnership(mountPoint, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+
+ if err := chown.ChangeHostPathOwnership(contentDir, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+ }
+ }
+ g.AddMount(overlayMount)
+ } else {
+ volMount := spec.Mount{
+ Type: "bind",
+ Source: mountPoint,
+ Destination: namedVol.Dest,
+ Options: namedVol.Options,
+ }
+ g.AddMount(volMount)
}
- g.AddMount(volMount)
}
// Check if the spec file mounts contain the options z, Z or U.
@@ -566,7 +599,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if isGIDAvailable {
g.AddProcessAdditionalGid(uint32(gid))
} else {
- logrus.Warnf("additional gid=%d is not present in the user namespace, skip setting it", gid)
+ logrus.Warnf("Additional gid=%d is not present in the user namespace, skip setting it", gid)
}
}
}
@@ -607,7 +640,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
if os.IsNotExist(err) {
// The kernel-provided files only exist if user namespaces are supported
- logrus.Debugf("user or group ID mappings not available: %s", err)
+ logrus.Debugf("User or group ID mappings not available: %s", err)
} else {
return nil, err
}
@@ -748,7 +781,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
if rootPropagation != "" {
- logrus.Debugf("set root propagation to %q", rootPropagation)
+ logrus.Debugf("Set root propagation to %q", rootPropagation)
if err := g.SetLinuxRootPropagation(rootPropagation); err != nil {
return nil, err
}
@@ -805,7 +838,7 @@ func (c *Container) mountNotifySocket(g generate.Generator) error {
}
notifyDir := filepath.Join(c.bundlePath(), "notify")
- logrus.Debugf("checking notify %q dir", notifyDir)
+ logrus.Debugf("Checking notify %q dir", notifyDir)
if err := os.MkdirAll(notifyDir, 0755); err != nil {
if !os.IsExist(err) {
return errors.Wrapf(err, "unable to create notify %q dir", notifyDir)
@@ -814,7 +847,7 @@ func (c *Container) mountNotifySocket(g generate.Generator) error {
if err := label.Relabel(notifyDir, c.MountLabel(), true); err != nil {
return errors.Wrapf(err, "relabel failed %q", notifyDir)
}
- logrus.Debugf("add bindmount notify %q dir", notifyDir)
+ logrus.Debugf("Add bindmount notify %q dir", notifyDir)
if _, ok := c.state.BindMounts["/run/notify"]; !ok {
c.state.BindMounts["/run/notify"] = notifyDir
}
@@ -1166,7 +1199,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
for _, del := range cleanup {
file := filepath.Join(c.bundlePath(), del)
if err := os.Remove(file); err != nil {
- logrus.Debugf("unable to remove file %s", file)
+ logrus.Debugf("Unable to remove file %s", file)
}
}
}
@@ -1266,7 +1299,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
var netStatus map[string]types.StatusBlock
_, err := metadata.ReadJSONFile(&netStatus, c.bundlePath(), metadata.NetworkStatusFile)
if err != nil {
- logrus.Infof("failed to unmarshal network status, cannot restore the same ip/mac: %v", err)
+ logrus.Infof("Failed to unmarshal network status, cannot restore the same ip/mac: %v", err)
}
// If the restored container should get a new name, the IP address of
// the container will not be restored. This assumes that if a new name is
@@ -1277,7 +1310,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err == nil && options.Name == "" && (!options.IgnoreStaticIP || !options.IgnoreStaticMAC) {
// The file with the network.status does exist. Let's restore the
// container with the same networks settings as during checkpointing.
- aliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ aliases, err := c.GetAllNetworkAliases()
if err != nil {
return err
}
@@ -1316,7 +1349,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
defer func() {
if retErr != nil {
if err := c.cleanup(ctx); err != nil {
- logrus.Errorf("error cleaning up container %s: %v", c.ID(), err)
+ logrus.Errorf("Cleaning up container %s: %v", c.ID(), err)
}
}
}()
@@ -1870,11 +1903,11 @@ func (c *Container) generateResolvConf() (string, error) {
for _, nsIP := range status.DNSServerIPs {
networkNameServers = append(networkNameServers, nsIP.String())
}
- logrus.Debugf("adding nameserver(s) from network status of '%q'", status.DNSServerIPs)
+ logrus.Debugf("Adding nameserver(s) from network status of '%q'", status.DNSServerIPs)
}
if status.DNSSearchDomains != nil {
networkSearchDomains = append(networkSearchDomains, status.DNSSearchDomains...)
- logrus.Debugf("adding search domain(s) from network status of '%q'", status.DNSSearchDomains)
+ logrus.Debugf("Adding search domain(s) from network status of '%q'", status.DNSSearchDomains)
}
}
@@ -1923,7 +1956,7 @@ func (c *Container) generateResolvConf() (string, error) {
if c.config.NetMode.IsSlirp4netns() {
slirp4netnsDNS, err := GetSlirp4netnsDNS(c.slirp4netnsSubnet)
if err != nil {
- logrus.Warn("failed to determine Slirp4netns DNS: ", err.Error())
+ logrus.Warn("Failed to determine Slirp4netns DNS: ", err.Error())
} else {
nameservers = append([]string{slirp4netnsDNS.String()}, nameservers...)
}
@@ -2025,7 +2058,7 @@ func (c *Container) getHosts() string {
// When using slirp4netns, the interface gets a static IP
slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet)
if err != nil {
- logrus.Warnf("failed to determine slirp4netnsIP: %v", err.Error())
+ logrus.Warnf("Failed to determine slirp4netnsIP: %v", err.Error())
} else {
hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", slirp4netnsIP.String(), c.Hostname(), c.config.Name)
}
@@ -2050,35 +2083,39 @@ func (c *Container) getHosts() string {
}
}
- // Add gateway entry
- var depCtr *Container
- netStatus := c.getNetworkStatus()
- if c.config.NetNsCtr != "" {
- // ignoring the error because there isn't anything to do
- depCtr, _ = c.getRootNetNsDepCtr()
- } else if len(netStatus) != 0 {
- depCtr = c
- }
-
- if depCtr != nil {
- for _, status := range depCtr.getNetworkStatus() {
- for _, netInt := range status.Interfaces {
- for _, netAddress := range netInt.Networks {
- if netAddress.Gateway != nil {
- hosts += fmt.Sprintf("%s host.containers.internal\n", netAddress.Gateway.String())
+ // Add gateway entry if we are not in a machine. If we use podman machine
+ // the gvproxy dns server will take care of host.containers.internal.
+ // https://github.com/containers/gvisor-tap-vsock/commit/1108ea45162281046d239047a6db9bc187e64b08
+ if !c.runtime.config.Engine.MachineEnabled {
+ var depCtr *Container
+ netStatus := c.getNetworkStatus()
+ if c.config.NetNsCtr != "" {
+ // ignoring the error because there isn't anything to do
+ depCtr, _ = c.getRootNetNsDepCtr()
+ } else if len(netStatus) != 0 {
+ depCtr = c
+ }
+
+ if depCtr != nil {
+ for _, status := range depCtr.getNetworkStatus() {
+ for _, netInt := range status.Interfaces {
+ for _, netAddress := range netInt.Networks {
+ if netAddress.Gateway != nil {
+ hosts += fmt.Sprintf("%s host.containers.internal\n", netAddress.Gateway.String())
+ }
}
}
}
- }
- } else if c.config.NetMode.IsSlirp4netns() {
- gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
- if err != nil {
- logrus.Warn("failed to determine gatewayIP: ", err.Error())
+ } else if c.config.NetMode.IsSlirp4netns() {
+ gatewayIP, err := GetSlirp4netnsGateway(c.slirp4netnsSubnet)
+ if err != nil {
+ logrus.Warn("Failed to determine gatewayIP: ", err.Error())
+ } else {
+ hosts += fmt.Sprintf("%s host.containers.internal\n", gatewayIP.String())
+ }
} else {
- hosts += fmt.Sprintf("%s host.containers.internal\n", gatewayIP.String())
+ logrus.Debug("Network configuration does not support host.containers.internal address")
}
- } else {
- logrus.Debug("network configuration does not support host.containers.internal address")
}
return hosts
diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go
deleted file mode 100644
index 125329ce5..000000000
--- a/libpod/container_internal_unsupported.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
-
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/pkg/lookup"
- spec "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-func (c *Container) mountSHM(shmOptions string) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) unmountSHM(mount string) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) prepare() error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) cleanupNetwork() error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
- return nil, define.ErrNotImplemented
-}
-
-func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) copyOwnerAndPerms(source, dest string) error {
- return nil
-}
-
-func (c *Container) getOCICgroupPath() (string, error) {
- return "", define.ErrNotImplemented
-}
-
-func (c *Container) cleanupOverlayMounts() error {
- return nil
-}
-
-func (c *Container) reloadNetwork() error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) getUserOverrides() *lookup.Overrides {
- return nil
-}
-
-// Fix ownership and permissions of the specified volume if necessary.
-func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
- return define.ErrNotImplemented
-}
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 89dd5e8b0..18840bff2 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -18,7 +18,7 @@ import (
var logDrivers []string
func init() {
- logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging)
+ logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging, define.PassthroughLogging)
}
// Log is a runtime function that can read one or more container logs.
@@ -34,6 +34,8 @@ func (r *Runtime) Log(ctx context.Context, containers []*Container, options *log
// ReadLog reads a containers log based on the input options and returns log lines over a channel.
func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
switch c.LogDriver() {
+ case define.PassthroughLogging:
+ return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot read logs")
case define.NoLogging:
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs")
case define.JournaldLogging:
@@ -83,7 +85,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
}
nll, err := logs.NewLogLine(line.Text)
if err != nil {
- logrus.Errorf("Error getting new log line: %v", err)
+ logrus.Errorf("Getting new log line: %v", err)
continue
}
if nll.Partial() {
@@ -108,7 +110,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
state, err := c.State()
if err != nil || state != define.ContainerStateRunning {
if err != nil && errors.Cause(err) != define.ErrNoSuchCtr {
- logrus.Errorf("Error getting container state: %v", err)
+ logrus.Errorf("Getting container state: %v", err)
}
go func() {
// Make sure to wait at least for the poll duration
@@ -116,7 +118,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
time.Sleep(watch.POLL_DURATION)
tailError := t.StopAtEOF()
if tailError != nil && tailError.Error() != "tail: stop at eof" {
- logrus.Errorf("Error stopping logger: %v", tailError)
+ logrus.Errorf("Stopping logger: %v", tailError)
}
}()
return nil
@@ -132,7 +134,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
}
go func() {
if err := c.runtime.Events(ctx, eventOptions); err != nil {
- logrus.Errorf("Error waiting for container to exit: %v", err)
+ logrus.Errorf("Waiting for container to exit: %v", err)
}
}()
// Now wait for the died event and signal to finish
@@ -143,7 +145,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
time.Sleep(watch.POLL_DURATION)
tailError := t.StopAtEOF()
if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" {
- logrus.Errorf("Error stopping logger: %v", tailError)
+ logrus.Errorf("Stopping logger: %v", tailError)
}
}()
}
diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go
index ec7306ca1..bb2ef1a73 100644
--- a/libpod/container_path_resolution.go
+++ b/libpod/container_path_resolution.go
@@ -112,7 +112,7 @@ func (c *Container) resolvePath(mountPoint string, containerPath string) (string
func findVolume(c *Container, containerPath string) (*Volume, error) {
runtime := c.Runtime()
cleanedContainerPath := filepath.Clean(containerPath)
- for _, vol := range c.Config().NamedVolumes {
+ for _, vol := range c.config.NamedVolumes {
if cleanedContainerPath == filepath.Clean(vol.Dest) {
return runtime.GetVolume(vol.Name)
}
@@ -124,7 +124,7 @@ func findVolume(c *Container, containerPath string) (*Volume, error) {
// Volume's destination.
func isPathOnVolume(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
- for _, vol := range c.Config().NamedVolumes {
+ for _, vol := range c.config.NamedVolumes {
if cleanedContainerPath == filepath.Clean(vol.Dest) {
return true
}
@@ -141,7 +141,7 @@ func isPathOnVolume(c *Container, containerPath string) bool {
// path of a Mount. Returns a matching Mount or nil.
func findBindMount(c *Container, containerPath string) *specs.Mount {
cleanedPath := filepath.Clean(containerPath)
- for _, m := range c.Config().Spec.Mounts {
+ for _, m := range c.config.Spec.Mounts {
if m.Type != "bind" {
continue
}
@@ -157,7 +157,7 @@ func findBindMount(c *Container, containerPath string) *specs.Mount {
// Mount's destination.
func isPathOnBindMount(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
- for _, m := range c.Config().Spec.Mounts {
+ for _, m := range c.config.Spec.Mounts {
if cleanedContainerPath == filepath.Clean(m.Destination) {
return true
}
diff --git a/libpod/container_stat_unsupported.go b/libpod/container_stat_unsupported.go
deleted file mode 100644
index c002e4d32..000000000
--- a/libpod/container_stat_unsupported.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
-
- "github.com/containers/podman/v3/libpod/define"
-)
-
-func (c *Container) stat(ctx context.Context, containerMountPoint string, containerPath string) (*define.FileInfo, string, string, error) {
- return nil, "", "", nil
-}
diff --git a/libpod/container_top_unsupported.go b/libpod/container_top_unsupported.go
deleted file mode 100644
index 1a096d248..000000000
--- a/libpod/container_top_unsupported.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build !linux
-
-package libpod
-
-import "github.com/containers/podman/v3/libpod/define"
-
-// Top gathers statistics about the running processes in a container. It returns a
-// []string for output
-func (c *Container) Top(descriptors []string) ([]string, error) {
- return nil, define.ErrNotImplemented
-}
-
-// GetContainerPidInformation returns process-related data of all processes in
-// the container. The output data can be controlled via the `descriptors`
-// argument which expects format descriptors and supports all AIXformat
-// descriptors of ps (1) plus some additional ones to for instance inspect the
-// set of effective capabilities. Each element in the returned string slice
-// is a tab-separated string.
-//
-// For more details, please refer to github.com/containers/psgo.
-func (c *Container) GetContainerPidInformation(descriptors []string) ([]string, error) {
- return nil, define.ErrNotImplemented
-}
diff --git a/libpod/container_unsupported.go b/libpod/container_unsupported.go
deleted file mode 100644
index e214b9465..000000000
--- a/libpod/container_unsupported.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// +build !linux
-
-package libpod
-
-type containerPlatformState struct{}
diff --git a/libpod/define/config.go b/libpod/define/config.go
index 6c426f2ec..a5cf07afc 100644
--- a/libpod/define/config.go
+++ b/libpod/define/config.go
@@ -78,6 +78,9 @@ const JSONLogging = "json-file"
// NoLogging is the string conmon expects when specifying to use no log driver whatsoever
const NoLogging = "none"
+// PassthroughLogging is the string conmon expects when specifying to use the passthrough driver
+const PassthroughLogging = "passthrough"
+
// Strings used for --sdnotify option to podman
const (
SdNotifyModeContainer = "container"
@@ -87,3 +90,6 @@ const (
// DefaultRlimitValue is the value set by default for nofile and nproc
const RLimitDefaultValue = uint64(1048576)
+
+// BindMountPrefix distinguishes its annotations from others
+const BindMountPrefix = "bind-mount-options:"
diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go
index 90703a807..7decb18a8 100644
--- a/libpod/define/container_inspect.go
+++ b/libpod/define/container_inspect.go
@@ -202,10 +202,16 @@ type InspectContainerState struct {
Error string `json:"Error"` // TODO
StartedAt time.Time `json:"StartedAt"`
FinishedAt time.Time `json:"FinishedAt"`
- Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"`
+ Health HealthCheckResults `json:"Health,omitempty"`
Checkpointed bool `json:"Checkpointed,omitempty"`
}
+// Healthcheck returns the HealthCheckResults. This is used for old podman compat
+// to make the "Healthcheck" key available in the go template.
+func (s *InspectContainerState) Healthcheck() HealthCheckResults {
+ return s.Health
+}
+
// HealthCheckResults describes the results/logs from a healthcheck
type HealthCheckResults struct {
// Status healthy or unhealthy
diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go
index b7a6e76b5..e78d97850 100644
--- a/libpod/define/pod_inspect.go
+++ b/libpod/define/pod_inspect.go
@@ -59,6 +59,8 @@ type InspectPodData struct {
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
// Mounts contains volume related information for the pod
Mounts []InspectMount `json:"mounts,omitempty"`
+ // Devices contains the specified host devices
+ Devices []InspectDevice `json:"devices,omitempty"`
}
// InspectPodInfraConfig contains the configuration of the pod's infra
diff --git a/libpod/events.go b/libpod/events.go
index 22c51aeec..342af02d2 100644
--- a/libpod/events.go
+++ b/libpod/events.go
@@ -33,7 +33,7 @@ func (c *Container) newContainerEvent(status events.Status) {
}
if err := c.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write pod event: %q", err)
+ logrus.Errorf("Unable to write pod event: %q", err)
}
}
@@ -46,7 +46,7 @@ func (c *Container) newContainerExitedEvent(exitCode int32) {
e.Type = events.Container
e.ContainerExitCode = int(exitCode)
if err := c.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write container exited event: %q", err)
+ logrus.Errorf("Unable to write container exited event: %q", err)
}
}
@@ -61,7 +61,7 @@ func (c *Container) newExecDiedEvent(sessionID string, exitCode int) {
e.Attributes = make(map[string]string)
e.Attributes["execID"] = sessionID
if err := c.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write exec died event: %q", err)
+ logrus.Errorf("Unable to write exec died event: %q", err)
}
}
@@ -73,7 +73,7 @@ func (c *Container) newNetworkEvent(status events.Status, netName string) {
e.Type = events.Network
e.Network = netName
if err := c.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write pod event: %q", err)
+ logrus.Errorf("Unable to write pod event: %q", err)
}
}
@@ -84,7 +84,7 @@ func (p *Pod) newPodEvent(status events.Status) {
e.Name = p.Name()
e.Type = events.Pod
if err := p.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write pod event: %q", err)
+ logrus.Errorf("Unable to write pod event: %q", err)
}
}
@@ -94,7 +94,7 @@ func (r *Runtime) newSystemEvent(status events.Status) {
e.Type = events.System
if err := r.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write system event: %q", err)
+ logrus.Errorf("Unable to write system event: %q", err)
}
}
@@ -104,7 +104,7 @@ func (v *Volume) newVolumeEvent(status events.Status) {
e.Name = v.Name()
e.Type = events.Volume
if err := v.runtime.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write volume event: %q", err)
+ logrus.Errorf("Unable to write volume event: %q", err)
}
}
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 3e16d8679..72e03355a 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -195,7 +195,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) { /
if code, ok := entry.Fields["PODMAN_EXIT_CODE"]; ok {
intCode, err := strconv.Atoi(code)
if err != nil {
- logrus.Errorf("Error parsing event exit code %s", code)
+ logrus.Errorf("Parsing event exit code %s", code)
} else {
newEvent.ContainerExitCode = intCode
}
diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go
index c32ba85cb..91f031513 100644
--- a/libpod/healthcheck.go
+++ b/libpod/healthcheck.go
@@ -162,7 +162,7 @@ func newHealthCheckLog(start, end time.Time, exitCode int, log string) define.He
// updatedHealthCheckStatus updates the health status of the container
// in the healthcheck log
func (c *Container) updateHealthStatus(status string) error {
- healthCheck, err := c.GetHealthCheckLog()
+ healthCheck, err := c.getHealthCheckLog()
if err != nil {
return err
}
@@ -176,7 +176,7 @@ func (c *Container) updateHealthStatus(status string) error {
// UpdateHealthCheckLog parses the health check results and writes the log
func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPeriod bool) error {
- healthCheck, err := c.GetHealthCheckLog()
+ healthCheck, err := c.getHealthCheckLog()
if err != nil {
return err
}
@@ -213,10 +213,11 @@ func (c *Container) healthCheckLogPath() string {
return filepath.Join(filepath.Dir(c.state.RunDir), "healthcheck.log")
}
-// GetHealthCheckLog returns HealthCheck results by reading the container's
+// getHealthCheckLog returns HealthCheck results by reading the container's
// health check log file. If the health check log file does not exist, then
// an empty healthcheck struct is returned
-func (c *Container) GetHealthCheckLog() (define.HealthCheckResults, error) {
+// The caller should lock the container before this function is called.
+func (c *Container) getHealthCheckLog() (define.HealthCheckResults, error) {
var healthCheck define.HealthCheckResults
if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) {
return healthCheck, nil
@@ -236,7 +237,12 @@ func (c *Container) HealthCheckStatus() (string, error) {
if !c.HasHealthCheck() {
return "", errors.Errorf("container %s has no defined healthcheck", c.ID())
}
- results, err := c.GetHealthCheckLog()
+ c.lock.Lock()
+ defer c.lock.Unlock()
+ if err := c.syncContainer(); err != nil {
+ return "", err
+ }
+ results, err := c.getHealthCheckLog()
if err != nil {
return "", errors.Wrapf(err, "unable to get healthcheck log for %s", c.ID())
}
diff --git a/libpod/healthcheck_unsupported.go b/libpod/healthcheck_unsupported.go
deleted file mode 100644
index 8b6a0209b..000000000
--- a/libpod/healthcheck_unsupported.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build !linux
-
-package libpod
-
-import "github.com/containers/podman/v3/libpod/define"
-
-// createTimer systemd timers for healthchecks of a container
-func (c *Container) createTimer() error {
- return define.ErrNotImplemented
-}
-
-// startTimer starts a systemd timer for the healthchecks
-func (c *Container) startTimer() error {
- return define.ErrNotImplemented
-}
-
-// removeTimer removes the systemd timer and unit files
-// for the container
-func (c *Container) removeTimer() error {
- return define.ErrNotImplemented
-}
diff --git a/libpod/info.go b/libpod/info.go
index 36dc8bc2a..a2fd18491 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -186,7 +186,7 @@ func (r *Runtime) hostInfo() (*define.HostInfo, error) {
conmonInfo, ociruntimeInfo, err := r.defaultOCIRuntime.RuntimeInfo()
if err != nil {
- logrus.Errorf("Error getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err)
+ logrus.Errorf("Getting info on OCI runtime %s: %v", r.defaultOCIRuntime.Name(), err)
} else {
info.Conmon = conmonInfo
info.OCIRuntime = ociruntimeInfo
diff --git a/libpod/kube.go b/libpod/kube.go
index 54e8a7c50..bf86a9d16 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -1,9 +1,11 @@
package libpod
import (
+ "context"
"fmt"
"math/rand"
"os"
+ "reflect"
"sort"
"strconv"
"strings"
@@ -11,6 +13,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
+ "github.com/containers/podman/v3/pkg/env"
"github.com/containers/podman/v3/pkg/lookup"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/specgen"
@@ -26,14 +29,14 @@ import (
// GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description that includes just a single container.
-func GenerateForKube(ctrs []*Container) (*v1.Pod, error) {
+func GenerateForKube(ctx context.Context, ctrs []*Container) (*v1.Pod, error) {
// Generate the v1.Pod yaml description
- return simplePodWithV1Containers(ctrs)
+ return simplePodWithV1Containers(ctx, ctrs)
}
// GenerateForKube takes a slice of libpod containers and generates
// one v1.Pod description
-func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
+func (p *Pod) GenerateForKube(ctx context.Context) (*v1.Pod, []v1.ServicePort, error) {
// Generate the v1.Pod yaml description
var (
ports []v1.ContainerPort //nolint
@@ -77,7 +80,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
servicePorts = containerPortsToServicePorts(ports)
hostNetwork = infraContainer.NetworkMode() == string(namespaces.NetworkMode(specgen.Host))
}
- pod, err := p.podWithContainers(allContainers, ports, hostNetwork)
+ pod, err := p.podWithContainers(ctx, allContainers, ports, hostNetwork)
if err != nil {
return nil, servicePorts, err
}
@@ -87,7 +90,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
// so set it at here
for _, ctr := range allContainers {
if !ctr.IsInfra() {
- switch ctr.Config().RestartPolicy {
+ switch ctr.config.RestartPolicy {
case define.RestartPolicyAlways:
pod.Spec.RestartPolicy = v1.RestartPolicyAlways
case define.RestartPolicyOnFailure:
@@ -217,7 +220,7 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
return sps
}
-func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) {
+func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) {
deDupPodVolumes := make(map[string]*v1.Volume)
first := true
podContainers := make([]v1.Container, 0, len(containers))
@@ -238,11 +241,13 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
isInit := ctr.IsInitCtr()
- ctr, volumes, _, err := containerToV1Container(ctr)
+ ctr, volumes, _, annotations, err := containerToV1Container(ctx, ctr)
if err != nil {
return nil, err
}
-
+ for k, v := range annotations {
+ podAnnotations[define.BindMountPrefix+k] = v
+ }
// Since port bindings for the pod are handled by the
// infra container, wipe them here.
ctr.Ports = nil
@@ -250,7 +255,9 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
// We add the original port declarations from the libpod infra container
// to the first kubernetes container description because otherwise we loose
// the original container/port bindings.
- if first && len(ports) > 0 {
+ // Add the port configuration to the first regular container or the first
+ // init container if only init containers have been created in the pod.
+ if first && len(ports) > 0 && (!isInit || len(containers) == 2) {
ctr.Ports = ports
first = false
}
@@ -266,7 +273,7 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
deDupPodVolumes[vol.Name] = &vol
}
} else {
- _, _, infraDNS, err := containerToV1Container(ctr)
+ _, _, infraDNS, _, err := containerToV1Container(ctx, ctr)
if err != nil {
return nil, err
}
@@ -336,7 +343,7 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta
// simplePodWithV1Containers is a function used by inspect when kube yaml needs to be generated
// for a single container. we "insert" that container description in a pod.
-func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
+func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod, error) {
kubeCtrs := make([]v1.Container, 0, len(ctrs))
kubeInitCtrs := []v1.Container{}
kubeVolumes := make([]v1.Volume, 0)
@@ -354,17 +361,19 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
if !ctr.HostNetwork() {
hostNetwork = false
}
- kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctr)
+ kubeCtr, kubeVols, ctrDNS, annotations, err := containerToV1Container(ctx, ctr)
if err != nil {
return nil, err
}
+ for k, v := range annotations {
+ kubeAnnotations[define.BindMountPrefix+k] = v
+ }
if isInit {
kubeInitCtrs = append(kubeInitCtrs, kubeCtr)
} else {
kubeCtrs = append(kubeCtrs, kubeCtr)
}
kubeVolumes = append(kubeVolumes, kubeVols...)
-
// Combine DNS information in sum'd structure
if ctrDNS != nil {
// nameservers
@@ -410,42 +419,44 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
// containerToV1Container converts information we know about a libpod container
// to a V1.Container specification.
-func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, error) {
+func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, map[string]string, error) {
kubeContainer := v1.Container{}
kubeVolumes := []v1.Volume{}
+ annotations := make(map[string]string)
kubeSec, err := generateKubeSecurityContext(c)
if err != nil {
- return kubeContainer, kubeVolumes, nil, err
+ return kubeContainer, kubeVolumes, nil, annotations, err
}
// NOTE: a privileged container mounts all of /dev/*.
if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 {
// TODO Enable when we can support devices and their names
- kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.Spec().Linux.Devices)
- return kubeContainer, kubeVolumes, nil, errors.Wrapf(define.ErrNotImplemented, "linux devices")
+ kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices)
+ return kubeContainer, kubeVolumes, nil, annotations, errors.Wrapf(define.ErrNotImplemented, "linux devices")
}
if len(c.config.UserVolumes) > 0 {
- volumeMounts, volumes, err := libpodMountsToKubeVolumeMounts(c)
+ volumeMounts, volumes, localAnnotations, err := libpodMountsToKubeVolumeMounts(c)
if err != nil {
- return kubeContainer, kubeVolumes, nil, err
+ return kubeContainer, kubeVolumes, nil, nil, err
}
+ annotations = localAnnotations
kubeContainer.VolumeMounts = volumeMounts
kubeVolumes = append(kubeVolumes, volumes...)
}
envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env)
if err != nil {
- return kubeContainer, kubeVolumes, nil, err
+ return kubeContainer, kubeVolumes, nil, annotations, err
}
portmappings, err := c.PortMappings()
if err != nil {
- return kubeContainer, kubeVolumes, nil, err
+ return kubeContainer, kubeVolumes, nil, annotations, err
}
ports, err := ocicniPortMappingToContainerPort(portmappings)
if err != nil {
- return kubeContainer, kubeVolumes, nil, err
+ return kubeContainer, kubeVolumes, nil, annotations, err
}
// Handle command and arguments.
@@ -462,6 +473,17 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS
_, image := c.Image()
kubeContainer.Image = image
kubeContainer.Stdin = c.Stdin()
+ img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil)
+ if err != nil {
+ return kubeContainer, kubeVolumes, nil, annotations, err
+ }
+ imgData, err := img.Inspect(ctx, false)
+ if err != nil {
+ return kubeContainer, kubeVolumes, nil, annotations, err
+ }
+ if reflect.DeepEqual(imgData.Config.Cmd, kubeContainer.Command) {
+ kubeContainer.Command = nil
+ }
kubeContainer.WorkingDir = c.WorkingDir()
kubeContainer.Ports = ports
@@ -539,7 +561,7 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNS
}
dns.Options = dnsOptions
}
- return kubeContainer, kubeVolumes, &dns, nil
+ return kubeContainer, kubeVolumes, &dns, annotations, nil
}
// ocicniPortMappingToContainerPort takes an ocicni portmapping and converts
@@ -570,12 +592,16 @@ func ocicniPortMappingToContainerPort(portMappings []types.OCICNIPortMapping) ([
// libpodEnvVarsToKubeEnvVars converts a key=value string slice to []v1.EnvVar
func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
+ defaultEnv := env.DefaultEnvVariables()
envVars := make([]v1.EnvVar, 0, len(envs))
for _, e := range envs {
split := strings.SplitN(e, "=", 2)
if len(split) != 2 {
return envVars, errors.Errorf("environment variable %s is malformed; should be key=value", e)
}
+ if defaultEnv[split[0]] == split[1] {
+ continue
+ }
ev := v1.EnvVar{
Name: split[0],
Value: split[1],
@@ -586,16 +612,23 @@ func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
}
// libpodMountsToKubeVolumeMounts converts the containers mounts to a struct kube understands
-func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, error) {
+func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume, map[string]string, error) {
namedVolumes, mounts := c.sortUserVolumes(c.config.Spec)
vms := make([]v1.VolumeMount, 0, len(mounts))
vos := make([]v1.Volume, 0, len(mounts))
+ annotations := make(map[string]string)
var suffix string
for index, m := range mounts {
+ for _, opt := range m.Options {
+ if opt == "Z" || opt == "z" {
+ annotations[m.Source] = opt
+ break
+ }
+ }
vm, vo, err := generateKubeVolumeMount(m)
if err != nil {
- return vms, vos, err
+ return vms, vos, annotations, err
}
// Name will be the same, so use the index as suffix
suffix = fmt.Sprintf("-%d", index)
@@ -609,7 +642,7 @@ func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume
vms = append(vms, vm)
vos = append(vos, vo)
}
- return vms, vos, nil
+ return vms, vos, annotations, nil
}
// generateKubePersistentVolumeClaim converts a ContainerNamedVolume to a Kubernetes PersistentVolumeClaim
diff --git a/libpod/lock/file/file_lock.go b/libpod/lock/file/file_lock.go
index 2643c9211..4685872b6 100644
--- a/libpod/lock/file/file_lock.go
+++ b/libpod/lock/file/file_lock.go
@@ -139,7 +139,7 @@ func (locks *FileLocks) DeallocateAllLocks() error {
err := os.Remove(p)
if err != nil {
lastErr = err
- logrus.Errorf("deallocating lock %s", p)
+ logrus.Errorf("Deallocating lock %s", p)
}
}
return lastErr
diff --git a/libpod/lock/shm/shm_lock_nocgo.go b/libpod/lock/shm/shm_lock_nocgo.go
index ea1488c90..627344d9c 100644
--- a/libpod/lock/shm/shm_lock_nocgo.go
+++ b/libpod/lock/shm/shm_lock_nocgo.go
@@ -16,7 +16,7 @@ type SHMLocks struct {
// numLocks must not be 0, and may be rounded up to a multiple of the bitmap
// size used by the underlying implementation.
func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return &SHMLocks{}, nil
}
@@ -24,13 +24,13 @@ func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
// POSIX semaphores. numLocks must match the number of locks the shared memory
// segment was created with.
func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return &SHMLocks{}, nil
}
// GetMaxLocks returns the maximum number of locks in the SHM
func (locks *SHMLocks) GetMaxLocks() uint32 {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return 0
}
@@ -40,7 +40,7 @@ func (locks *SHMLocks) GetMaxLocks() uint32 {
// fail to release, causing a program freeze.
// Close() is only intended to be used while testing the locks.
func (locks *SHMLocks) Close() error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
@@ -50,7 +50,7 @@ func (locks *SHMLocks) Close() error {
// Allocations past the maximum number of locks given when the SHM segment was
// created will result in an error, and no semaphore will be allocated.
func (locks *SHMLocks) AllocateSemaphore() (uint32, error) {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return 0, nil
}
@@ -59,7 +59,7 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) {
// If the semaphore is already in use or the index is invalid an error will be
// returned.
func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
@@ -67,14 +67,14 @@ func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error {
// reallocated to another container or pod.
// The given semaphore must be already allocated, or an error will be returned.
func (locks *SHMLocks) DeallocateSemaphore(sem uint32) error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
// DeallocateAllSemaphores frees all semaphores so they can be reallocated to
// other containers and pods.
func (locks *SHMLocks) DeallocateAllSemaphores() error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
@@ -86,7 +86,7 @@ func (locks *SHMLocks) DeallocateAllSemaphores() error {
// but before the caller has queried the database to determine this, will
// succeed.
func (locks *SHMLocks) LockSemaphore(sem uint32) error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
@@ -97,6 +97,6 @@ func (locks *SHMLocks) LockSemaphore(sem uint32) error {
// but before the caller has queried the database to determine this, will
// succeed.
func (locks *SHMLocks) UnlockSemaphore(sem uint32) error {
- logrus.Error("locks are not supported without cgo")
+ logrus.Error("Locks are not supported without cgo")
return nil
}
diff --git a/libpod/logs/log.go b/libpod/logs/log.go
index a584de0ee..19a121fe9 100644
--- a/libpod/logs/log.go
+++ b/libpod/logs/log.go
@@ -267,6 +267,6 @@ func (l *LogLine) Write(stdout io.Writer, stderr io.Writer, logOpts *LogOptions)
}
default:
// Warn the user if the device type does not match. Most likely the file is corrupted.
- logrus.Warnf("unknown Device type '%s' in log file from Container %s", l.Device, l.CID)
+ logrus.Warnf("Unknown Device type '%s' in log file from Container %s", l.Device, l.CID)
}
}
diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go
index d69dd7eb3..93d871767 100644
--- a/libpod/network/cni/cni_conversion.go
+++ b/libpod/network/cni/cni_conversion.go
@@ -14,7 +14,6 @@ import (
"time"
"github.com/containernetworking/cni/libcni"
- "github.com/containernetworking/cni/pkg/version"
"github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/libpod/network/util"
pkgutil "github.com/containers/podman/v3/pkg/util"
@@ -105,7 +104,7 @@ func createNetworkFromCNIConfigList(conf *libcni.NetworkConfigList, confPath str
default:
// A warning would be good but users would get this warning everytime so keep this at info level.
- logrus.Infof("unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information",
+ logrus.Infof("Unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information",
firstPlugin.Network.Type, confPath)
}
@@ -283,7 +282,10 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ
ipMasq = false
}
// create CNI plugin configuration
- ncList := newNcList(network.Name, version.Current(), network.Labels, network.Options)
+ // explicitly use CNI version 0.4.0 here, to use v1.0.0 at least containernetwork-plugins-1.0.1 has to be installed
+ // the dnsname plugin also needs to be updated for 1.0.0
+ // TODO change to 1.0.0 when most distros support it
+ ncList := newNcList(network.Name, "0.4.0", network.Labels, network.Options)
var plugins []interface{}
switch network.Driver {
diff --git a/libpod/network/cni/cni_exec.go b/libpod/network/cni/cni_exec.go
index c4d7f49f7..ae857bcfb 100644
--- a/libpod/network/cni/cni_exec.go
+++ b/libpod/network/cni/cni_exec.go
@@ -30,6 +30,7 @@ import (
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/version"
+ "github.com/containers/podman/v3/pkg/rootless"
)
type cniExec struct {
@@ -67,6 +68,17 @@ func (e *cniExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData [
c.Stdout = stdout
c.Stderr = stderr
+ // The dnsname plugin tries to use XDG_RUNTIME_DIR to store files.
+ // podman run will have XDG_RUNTIME_DIR set and thus the cni plugin can use
+ // it. The problem is that XDG_RUNTIME_DIR is unset for the conmon process
+ // for rootful users. This causes issues since the cleanup process is spawned
+ // by conmon and thus not have XDG_RUNTIME_DIR set to same value as podman run.
+ // Because of it dnsname will not find the config files and cannot correctly cleanup.
+ // To fix this we should also unset XDG_RUNTIME_DIR for the cni plugins as rootful.
+ if !rootless.IsRootless() {
+ c.Env = append(c.Env, "XDG_RUNTIME_DIR=")
+ }
+
err := c.Run()
if err != nil {
return nil, annotatePluginError(err, pluginPath, stdout.Bytes(), stderr.Bytes())
diff --git a/libpod/network/cni/config.go b/libpod/network/cni/config.go
index 2a6ad8eb3..3df155637 100644
--- a/libpod/network/cni/config.go
+++ b/libpod/network/cni/config.go
@@ -162,7 +162,7 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error {
err = netlink.LinkDel(link)
// only log the error, it is not fatal
if err != nil {
- logrus.Infof("failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err)
+ logrus.Infof("Failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err)
}
}
}
@@ -170,7 +170,11 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error {
file := network.filename
delete(n.networks, network.libpodNet.Name)
- return os.Remove(file)
+ // make sure to not error for ErrNotExist
+ if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) {
+ return err
+ }
+ return nil
}
// NetworkList will return all known Networks. Optionally you can
diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go
index a0a0ea1af..288cf4626 100644
--- a/libpod/network/cni/config_test.go
+++ b/libpod/network/cni/config_test.go
@@ -1021,6 +1021,27 @@ var _ = Describe("Config", func() {
Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config"))
})
+ It("remove network should not error when config file does not exists on disk", func() {
+ name := "mynet"
+ network := types.Network{Name: name}
+ _, err := libpodNet.NetworkCreate(network)
+ Expect(err).To(BeNil())
+
+ path := filepath.Join(cniConfDir, name+".conflist")
+ Expect(path).To(BeARegularFile())
+
+ err = os.Remove(path)
+ Expect(err).To(BeNil())
+ Expect(path).ToNot(BeARegularFile())
+
+ err = libpodNet.NetworkRemove(name)
+ Expect(err).To(BeNil())
+
+ nets, err := libpodNet.NetworkList()
+ Expect(err).To(BeNil())
+ Expect(nets).To(HaveLen(1))
+ Expect(nets).ToNot(ContainElement(HaveNetworkName(name)))
+ })
})
Context("network load valid existing ones", func() {
diff --git a/libpod/network/cni/network.go b/libpod/network/cni/network.go
index d77e63a5d..02801641e 100644
--- a/libpod/network/cni/network.go
+++ b/libpod/network/cni/network.go
@@ -127,7 +127,7 @@ func (n *cniNetwork) loadNetworks() error {
conf, err := libcni.ConfListFromFile(file)
if err != nil {
// do not log ENOENT errors
- if !os.IsNotExist(err) {
+ if !errors.Is(err, os.ErrNotExist) {
logrus.Warnf("Error loading CNI config file %s: %v", file, err)
}
continue
diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go
index b69953c4b..bd873f89b 100644
--- a/libpod/network/cni/run.go
+++ b/libpod/network/cni/run.go
@@ -10,7 +10,7 @@ import (
"github.com/containernetworking/cni/libcni"
cnitypes "github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/current"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
@@ -107,14 +107,9 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
return nil, retErr
}
- var cnires *current.Result
- cnires, retErr = current.GetResult(res)
- if retErr != nil {
- return nil, retErr
- }
- logrus.Debugf("cni result for container %s network %s: %v", options.ContainerID, name, cnires)
+ logrus.Debugf("cni result for container %s network %s: %v", options.ContainerID, name, res)
var status types.StatusBlock
- status, retErr = CNIResultToStatus(cnires)
+ status, retErr = CNIResultToStatus(res)
if retErr != nil {
return nil, retErr
}
@@ -125,8 +120,12 @@ func (n *cniNetwork) Setup(namespacePath string, options types.SetupOptions) (ma
// CNIResultToStatus convert the cni result to status block
// nolint:golint
-func CNIResultToStatus(cniResult *current.Result) (types.StatusBlock, error) {
+func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) {
result := types.StatusBlock{}
+ cniResult, err := types040.GetResult(res)
+ if err != nil {
+ return result, err
+ }
nameservers := make([]net.IP, 0, len(cniResult.DNS.Nameservers))
for _, nameserver := range cniResult.DNS.Nameservers {
ip := net.ParseIP(nameserver)
@@ -187,9 +186,6 @@ outer:
}
return errors.Errorf("requested static ip %s not in any subnet on network %s", ip.String(), network.libpodNet.Name)
}
- if len(netOpts.Aliases) > 0 && !network.libpodNet.DNSEnabled {
- return errors.New("cannot set aliases on a network without dns enabled")
- }
return nil
}
@@ -274,7 +270,7 @@ func (n *cniNetwork) teardown(namespacePath string, options types.TeardownOption
if err == nil {
rt = newRt
} else {
- logrus.Warnf("failed to load cached network config: %v, falling back to loading network %s from disk", err, name)
+ logrus.Warnf("Failed to load cached network config: %v, falling back to loading network %s from disk", err, name)
network := n.networks[name]
if network == nil {
multiErr = multierror.Append(multiErr, errors.Wrapf(define.ErrNoSuchNetwork, "network %s", name))
diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go
index f6da22a76..965203c2a 100644
--- a/libpod/network/cni/run_test.go
+++ b/libpod/network/cni/run_test.go
@@ -966,6 +966,26 @@ var _ = Describe("run CNI", func() {
})
})
+ It("setup with aliases but dns disabled should work", func() {
+ runTest(func() {
+ defNet := types.DefaultNetworkName
+ intName := "eth0"
+ setupOpts := types.SetupOptions{
+ NetworkOptions: types.NetworkOptions{
+ ContainerID: stringid.GenerateNonCryptoID(),
+ Networks: map[string]types.PerNetworkOptions{
+ defNet: {
+ InterfaceName: intName,
+ Aliases: []string{"somealias"},
+ },
+ },
+ },
+ }
+ _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
+ Expect(err).ToNot(HaveOccurred())
+ })
+ })
+
})
Context("invalid network setup test", func() {
@@ -1052,27 +1072,6 @@ var _ = Describe("run CNI", func() {
})
})
- It("setup with aliases but dns disabled", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- Aliases: []string{"somealias"},
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("cannot set aliases on a network without dns enabled"))
- })
- })
-
It("setup without networks", func() {
runTest(func() {
setupOpts := types.SetupOptions{
@@ -1256,7 +1255,7 @@ var _ = Describe("run CNI", func() {
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("network somenet: network not found"))
logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("failed to load cached network config"))
+ Expect(logString).To(ContainSubstring("Failed to load cached network config"))
})
})
@@ -1283,7 +1282,7 @@ var _ = Describe("run CNI", func() {
err = libpodNet.Teardown(netNSContainer.Path(), teardownOpts)
Expect(err).To(BeNil())
logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("failed to load cached network config"))
+ Expect(logString).To(ContainSubstring("Failed to load cached network config"))
})
})
})
diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go
index 6053ceb29..2fe4f3da2 100644
--- a/libpod/network/types/network.go
+++ b/libpod/network/types/network.go
@@ -32,11 +32,11 @@ type ContainerNetwork interface {
// Network describes the Network attributes.
type Network struct {
// Name of the Network.
- Name string `json:"name,omitempty"`
+ Name string `json:"name"`
// ID of the Network.
- ID string `json:"id,omitempty"`
+ ID string `json:"id"`
// Driver for this Network, e.g. bridge, macvlan...
- Driver string `json:"driver,omitempty"`
+ Driver string `json:"driver"`
// InterfaceName is the network interface name on the host.
NetworkInterface string `json:"network_interface,omitempty"`
// Created contains the timestamp when this network was created.
@@ -97,7 +97,7 @@ func (n *IPNet) UnmarshalText(text []byte) error {
type Subnet struct {
// Subnet for this Network in CIDR form.
// swagger:strfmt string
- Subnet IPNet `json:"subnet,omitempty"`
+ Subnet IPNet `json:"subnet"`
// Gateway IP for this Network.
// swagger:strfmt string
Gateway net.IP `json:"gateway,omitempty"`
@@ -134,14 +134,14 @@ type NetInterface struct {
// Networks list of assigned subnets with their gateway.
Networks []NetAddress `json:"networks,omitempty"`
// MacAddress for this Interface.
- MacAddress net.HardwareAddr `json:"mac_address,omitempty"`
+ MacAddress net.HardwareAddr `json:"mac_address"`
}
// NetAddress contains the subnet and gatway.
type NetAddress struct {
// Subnet of this NetAddress. Note that the subnet contains the
// actual ip of the net interface and not the network address.
- Subnet IPNet `json:"subnet,omitempty"`
+ Subnet IPNet `json:"subnet"`
// Gateway for the Subnet. This can be nil if there is no gateway, e.g. internal network.
Gateway net.IP `json:"gateway,omitempty"`
}
@@ -151,33 +151,35 @@ type PerNetworkOptions struct {
// StaticIPv4 for this container. Optional.
StaticIPs []net.IP `json:"static_ips,omitempty"`
// Aliases contains a list of names which the dns server should resolve
- // to this container. Can only be set when DNSEnabled is true on the Network.
+ // to this container. Should only be set when DNSEnabled is true on the Network.
+ // If aliases are set but there is no dns support for this network the
+ // network interface implementation should ignore this and NOT error.
// Optional.
Aliases []string `json:"aliases,omitempty"`
// StaticMac for this container. Optional.
StaticMAC net.HardwareAddr `json:"static_mac,omitempty"`
// InterfaceName for this container. Required.
- InterfaceName string `json:"interface_name,omitempty"`
+ InterfaceName string `json:"interface_name"`
}
// NetworkOptions for a given container.
type NetworkOptions struct {
// ContainerID is the container id, used for iptables comments and ipam allocation.
- ContainerID string `json:"container_id,omitempty"`
+ ContainerID string `json:"container_id"`
// ContainerName is the container name, used as dns name.
- ContainerName string `json:"container_name,omitempty"`
+ ContainerName string `json:"container_name"`
// PortMappings contains the port mappings for this container
PortMappings []PortMapping `json:"port_mappings,omitempty"`
// Networks contains all networks with the PerNetworkOptions.
// The map should contain at least one element.
- Networks map[string]PerNetworkOptions `json:"networks,omitempty"`
+ Networks map[string]PerNetworkOptions `json:"networks"`
}
// PortMapping is one or more ports that will be mapped into the container.
type PortMapping struct {
// HostIP is the IP that we will bind to on the host.
// If unset, assumed to be 0.0.0.0 (all interfaces).
- HostIP string `json:"host_ip,omitempty"`
+ HostIP string `json:"host_ip"`
// ContainerPort is the port number that will be exposed from the
// container.
// Mandatory.
@@ -186,7 +188,7 @@ type PortMapping struct {
// the container.
// If omitted, a random port on the host (guaranteed to be over 1024)
// will be assigned.
- HostPort uint16 `json:"host_port,omitempty"`
+ HostPort uint16 `json:"host_port"`
// Range is the number of ports that will be forwarded, starting at
// HostPort and ContainerPort and counting up.
// This is 1-indexed, so 1 is assumed to be a single port (only the
@@ -195,12 +197,12 @@ type PortMapping struct {
// If unset, assumed to be 1 (a single port).
// Both hostport + range and containerport + range must be less than
// 65536.
- Range uint16 `json:"range,omitempty"`
+ Range uint16 `json:"range"`
// Protocol is the protocol forward.
// Must be either "tcp", "udp", and "sctp", or some combination of these
// separated by commas.
// If unset, assumed to be TCP.
- Protocol string `json:"protocol,omitempty"`
+ Protocol string `json:"protocol"`
}
// OCICNIPortMapping maps to the standard CNI portmapping Capability.
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 96b6fb298..e792a410c 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -48,6 +48,41 @@ const (
persistentCNIDir = "/var/lib/cni"
)
+// GetAllNetworkAliases returns all configured aliases for this container.
+// It also adds the container short ID as alias to match docker.
+func (c *Container) GetAllNetworkAliases() (map[string][]string, error) {
+ allAliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ if err != nil {
+ return nil, err
+ }
+
+ // get the all attached networks, we cannot use GetAllNetworkAliases()
+ // since it returns nil if there are no aliases
+ nets, _, err := c.networks()
+ if err != nil {
+ return nil, err
+ }
+
+ // add container short ID as alias to match docker
+ for _, net := range nets {
+ allAliases[net] = append(allAliases[net], c.config.ID[:12])
+ }
+ return allAliases, nil
+}
+
+// GetNetworkAliases returns configured aliases for this network.
+// It also adds the container short ID as alias to match docker.
+func (c *Container) GetNetworkAliases(netName string) ([]string, error) {
+ aliases, err := c.runtime.state.GetNetworkAliases(c, netName)
+ if err != nil {
+ return nil, err
+ }
+
+ // add container short ID as alias to match docker
+ aliases = append(aliases, c.config.ID[:12])
+ return aliases, nil
+}
+
func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
opts := types.NetworkOptions{
ContainerID: c.config.ID,
@@ -61,7 +96,7 @@ func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
if err != nil {
return opts, err
}
- aliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ aliases, err := c.GetAllNetworkAliases()
if err != nil {
return opts, err
}
@@ -320,14 +355,14 @@ func (r *RootlessCNI) Cleanup(runtime *Runtime) error {
}
}
if err != nil {
- logrus.Errorf("failed to kill slirp4netns process: %s", err)
+ logrus.Errorf("Failed to kill slirp4netns process: %s", err)
}
err = os.RemoveAll(r.dir)
if err != nil {
logrus.Error(err)
}
} else if err != nil && !os.IsNotExist(err) {
- logrus.Errorf("could not read rootless cni directory, skipping cleanup: %s", err)
+ logrus.Errorf("Could not read rootless cni directory, skipping cleanup: %s", err)
}
}
return nil
@@ -458,7 +493,7 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
defer func() {
if err := cmd.Process.Release(); err != nil {
- logrus.Errorf("unable to release command process: %q", err)
+ logrus.Errorf("Unable to release command process: %q", err)
}
}()
@@ -635,10 +670,10 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.St
defer func() {
if retErr != nil {
if err := netns.UnmountNS(ctrNS); err != nil {
- logrus.Errorf("Error unmounting partially created network namespace for container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Unmounting partially created network namespace for container %s: %v", ctr.ID(), err)
}
if err := ctrNS.Close(); err != nil {
- logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Closing partially created network namespace for container %s: %v", ctr.ID(), err)
}
}
}()
@@ -872,7 +907,7 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
}
}
- aliases, err := ctr.runtime.state.GetAllNetworkAliases(ctr)
+ aliases, err := ctr.GetAllNetworkAliases()
if err != nil {
return nil, err
}
@@ -975,6 +1010,11 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
for _, net := range networks {
cniNet := new(define.InspectAdditionalNetwork)
cniNet.NetworkID = net
+ aliases, err := c.GetNetworkAliases(net)
+ if err != nil {
+ return nil, err
+ }
+ cniNet.Aliases = aliases
settings.Networks[net] = cniNet
}
}
@@ -1009,7 +1049,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
return nil, err
}
- aliases, err := c.runtime.state.GetNetworkAliases(c, name)
+ aliases, err := c.GetNetworkAliases(name)
if err != nil {
return nil, err
}
@@ -1222,6 +1262,14 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
// 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(aliases) > 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
+ }
+
if err := c.runtime.state.NetworkConnect(c, netName, aliases); err != nil {
return err
}
@@ -1253,6 +1301,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
if !exists {
return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)
}
+ aliases = append(aliases, c.config.ID[:12])
opts.Networks = map[string]types.PerNetworkOptions{
netName: {
Aliases: aliases,
diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go
index a5c035757..46cda89a9 100644
--- a/libpod/networking_slirp4netns.go
+++ b/libpod/networking_slirp4netns.go
@@ -210,7 +210,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
var err error
path, err = exec.LookPath("slirp4netns")
if err != nil {
- logrus.Errorf("could not find slirp4netns, the network namespace won't be configured: %v", err)
+ logrus.Errorf("Could not find slirp4netns, the network namespace won't be configured: %v", err)
return nil
}
}
@@ -222,7 +222,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
defer errorhandling.CloseQuiet(syncR)
defer errorhandling.CloseQuiet(syncW)
- havePortMapping := len(ctr.Config().PortMappings) > 0
+ havePortMapping := len(ctr.config.PortMappings) > 0
logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID))
ctrNetworkSlipOpts := []string{}
@@ -303,7 +303,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
defer func() {
servicereaper.AddPID(cmd.Process.Pid)
if err := cmd.Process.Release(); err != nil {
- logrus.Errorf("unable to release command process: %q", err)
+ logrus.Errorf("Unable to release command process: %q", err)
}
}()
@@ -421,7 +421,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t
if status.Exited() {
// Seek at the beginning of the file and read all its content
if _, err := logFile.Seek(0, 0); err != nil {
- logrus.Errorf("could not seek log file: %q", err)
+ logrus.Errorf("Could not seek log file: %q", err)
}
logContent, err := ioutil.ReadAll(logFile)
if err != nil {
@@ -506,7 +506,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin
defer func() {
servicereaper.AddPID(cmd.Process.Pid)
if err := cmd.Process.Release(); err != nil {
- logrus.Errorf("unable to release rootlessport process: %q", err)
+ logrus.Errorf("Unable to release rootlessport process: %q", err)
}
}()
if err := waitForSync(syncR, cmd, logFile, 3*time.Second); err != nil {
@@ -559,7 +559,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd
}
defer func() {
if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close connection: %q", err)
+ logrus.Errorf("Unable to close connection: %q", err)
}
}()
hostIP := i.HostIP
diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go
deleted file mode 100644
index 20c27ca7f..000000000
--- a/libpod/networking_unsupported.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
- "github.com/containers/podman/v3/libpod/define"
-)
-
-func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-func (r *Runtime) setupSlirp4netns(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-func (r *Runtime) setupNetNS(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-func (r *Runtime) teardownNetNS(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-func (r *Runtime) createNetNS(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) {
- return nil, define.ErrNotImplemented
-}
-
-func (r *Runtime) reloadContainerNetwork(ctr *Container) ([]*cnitypes.Result, error) {
- return nil, define.ErrNotImplemented
-}
-
-func getCNINetworksDir() (string, error) {
- return "", define.ErrNotImplemented
-}
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index de435b58a..d4d4a1076 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -40,7 +40,9 @@ func openUnixSocket(path string) (*net.UnixConn, error) {
// Does not check if state is appropriate
// started is only required if startContainer is true
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
- if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
+ passthrough := c.LogDriver() == define.PassthroughLogging
+
+ if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput && !passthrough {
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
}
if startContainer && started == nil {
@@ -52,24 +54,27 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
return err
}
- logrus.Debugf("Attaching to container %s", c.ID())
+ var conn *net.UnixConn
+ if !passthrough {
+ logrus.Debugf("Attaching to container %s", c.ID())
- registerResizeFunc(resize, c.bundlePath())
+ registerResizeFunc(resize, c.bundlePath())
- attachSock, err := c.AttachSocketPath()
- if err != nil {
- return err
- }
+ attachSock, err := c.AttachSocketPath()
+ if err != nil {
+ return err
+ }
- conn, err := openUnixSocket(attachSock)
- if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
- }
- defer func() {
- if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close socket: %q", err)
+ conn, err = openUnixSocket(attachSock)
+ if err != nil {
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
- }()
+ defer func() {
+ if err := conn.Close(); err != nil {
+ logrus.Errorf("unable to close socket: %q", err)
+ }
+ }()
+ }
// If starting was requested, start the container and notify when that's
// done.
@@ -80,6 +85,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
started <- true
}
+ if passthrough {
+ return nil
+ }
+
receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
if attachRdy != nil {
attachRdy <- true
@@ -142,7 +151,7 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
if newSize != nil {
err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize)
if err != nil {
- logrus.Warn("resize failed", err)
+ logrus.Warnf("Resize failed: %v", err)
}
}
@@ -153,7 +162,7 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se
}
defer func() {
if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close socket: %q", err)
+ logrus.Errorf("Unable to close socket: %q", err)
}
}()
@@ -210,7 +219,7 @@ func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detac
_, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys)
if err == nil {
if connErr := conn.CloseWrite(); connErr != nil {
- logrus.Errorf("unable to close conn: %q", connErr)
+ logrus.Errorf("Unable to close conn: %q", connErr)
}
}
}
diff --git a/libpod/oci_attach_unsupported.go b/libpod/oci_attach_unsupported.go
deleted file mode 100644
index 85e8b32e6..000000000
--- a/libpod/oci_attach_unsupported.go
+++ /dev/null
@@ -1,17 +0,0 @@
-//+build !linux
-
-package libpod
-
-import (
- "os"
-
- "github.com/containers/podman/v3/libpod/define"
-)
-
-func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
- return define.ErrNotImplemented
-}
-
-func (c *Container) attachToExec(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, sessionID string, startFd *os.File, attachFd *os.File) error {
- return define.ErrNotImplemented
-}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 5a7677b04..822377bfe 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -528,7 +528,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
if newSize != nil {
err = c.ociRuntime.ExecAttachResize(c, sessionID, *newSize)
if err != nil {
- logrus.Warn("resize failed", err)
+ logrus.Warnf("Resize failed: %v", err)
}
}
@@ -540,7 +540,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
}
defer func() {
if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close socket: %q", err)
+ logrus.Errorf("Unable to close socket: %q", err)
}
}()
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 831e89223..71a7b29fa 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -215,7 +215,7 @@ func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *Conta
}
defer func() {
if err := unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS); err != nil {
- logrus.Errorf("unable to clone new namespace: %q", err)
+ logrus.Errorf("Unable to clone new namespace: %q", err)
}
}()
@@ -524,7 +524,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
conn = newConn
defer func() {
if err := conn.Close(); err != nil {
- logrus.Errorf("unable to close container %s attach socket: %q", ctr.ID(), err)
+ logrus.Errorf("Unable to close container %s attach socket: %q", ctr.ID(), err)
}
}()
@@ -936,7 +936,7 @@ func waitPidStop(pid int, timeout time.Duration) error {
close(done)
return
}
- logrus.Errorf("Error pinging PID %d with signal 0: %v", pid, err)
+ logrus.Errorf("Pinging PID %d with signal 0: %v", pid, err)
}
time.Sleep(100 * time.Millisecond)
}
@@ -1150,7 +1150,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
if ctr.config.NetMode.IsSlirp4netns() || rootless.IsRootless() {
if ctr.config.PostConfigureNetNS {
- havePortMapping := len(ctr.Config().PortMappings) > 0
+ havePortMapping := len(ctr.config.PortMappings) > 0
if havePortMapping {
ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
if err != nil {
@@ -1199,7 +1199,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
pid, err := readConmonPipeData(parentSyncPipe, ociLog)
if err != nil {
if err2 := r.DeleteContainer(ctr); err2 != nil {
- logrus.Errorf("Error removing container %s from runtime after creation failed", ctr.ID())
+ logrus.Errorf("Removing container %s from runtime after creation failed", ctr.ID())
}
return err
}
@@ -1207,7 +1207,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
conmonPID, err := readConmonPidFile(ctr.config.ConmonPidFile)
if err != nil {
- logrus.Warnf("error reading conmon pid file for container %s: %v", ctr.ID(), err)
+ logrus.Warnf("Error reading conmon pid file for container %s: %v", ctr.ID(), err)
} else if conmonPID > 0 {
// conmon not having a pid file is a valid state, so don't set it if we don't have it
logrus.Infof("Got Conmon PID as %d", conmonPID)
@@ -1220,7 +1220,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
default:
if sent, err := daemon.SdNotify(false, fmt.Sprintf("MAINPID=%d", conmonPID)); err != nil {
- logrus.Errorf("Error notifying systemd of Conmon PID: %v", err)
+ logrus.Errorf("Notifying systemd of Conmon PID: %v", err)
} else if sent {
logrus.Debugf("Notify MAINPID sent successfully")
}
@@ -1288,6 +1288,8 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
logDriverArg = define.JournaldLogging
case define.NoLogging:
logDriverArg = define.NoLogging
+ case define.PassthroughLogging:
+ logDriverArg = define.PassthroughLogging
case define.JSONLogging:
fallthrough
//lint:ignore ST1015 the default case has to be here
@@ -1346,7 +1348,7 @@ func startCommandGivenSelinux(cmd *exec.Cmd, ctr *Container) error {
defer func() {
if err := os.Setenv("NOTIFY_SOCKET", ctr.notifySocket); err != nil {
- logrus.Errorf("Error resetting NOTIFY_SOCKET=%s", ctr.notifySocket)
+ logrus.Errorf("Resetting NOTIFY_SOCKET=%s", ctr.notifySocket)
}
}()
}
@@ -1385,7 +1387,7 @@ func startCommandGivenSelinux(cmd *exec.Cmd, ctr *Container) error {
// Ignore error returned from SetProcessLabel("") call,
// can't recover.
if labelErr := label.SetProcessLabel(""); labelErr != nil {
- logrus.Errorf("unable to set process label: %q", err)
+ logrus.Errorf("Unable to set process label: %q", err)
}
runtime.UnlockOSThread()
return err
@@ -1608,7 +1610,7 @@ func httpAttachTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, cid
numW, err2 := http.Write(buf[1:numR])
if err2 != nil {
if err != nil {
- logrus.Errorf("Error reading container %s STDOUT: %v", cid, err)
+ logrus.Errorf("Reading container %s STDOUT: %v", cid, err)
}
return err2
} else if numW+1 != numR {
@@ -1618,7 +1620,7 @@ func httpAttachTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter, cid
// there isn't a delay on the terminal side.
if err2 := http.Flush(); err2 != nil {
if err != nil {
- logrus.Errorf("Error reading container %s STDOUT: %v", cid, err)
+ logrus.Errorf("Reading container %s STDOUT: %v", cid, err)
}
return err2
}
@@ -1670,7 +1672,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter,
numH, err2 := http.Write(headerBuf)
if err2 != nil {
if err != nil {
- logrus.Errorf("Error reading container %s standard streams: %v", cid, err)
+ logrus.Errorf("Reading container %s standard streams: %v", cid, err)
}
return err2
@@ -1680,7 +1682,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter,
// of the protocol.
if numH != 8 {
if err != nil {
- logrus.Errorf("Error reading container %s standard streams: %v", cid, err)
+ logrus.Errorf("Reading container %s standard streams: %v", cid, err)
}
return io.ErrShortWrite
@@ -1689,13 +1691,13 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter,
numW, err2 := http.Write(buf[1:numR])
if err2 != nil {
if err != nil {
- logrus.Errorf("Error reading container %s standard streams: %v", cid, err)
+ logrus.Errorf("Reading container %s standard streams: %v", cid, err)
}
return err2
} else if numW+1 != numR {
if err != nil {
- logrus.Errorf("Error reading container %s standard streams: %v", cid, err)
+ logrus.Errorf("Reading container %s standard streams: %v", cid, err)
}
return io.ErrShortWrite
@@ -1704,7 +1706,7 @@ func httpAttachNonTerminalCopy(container *net.UnixConn, http *bufio.ReadWriter,
// there isn't a delay on the terminal side.
if err2 := http.Flush(); err2 != nil {
if err != nil {
- logrus.Errorf("Error reading container %s STDOUT: %v", cid, err)
+ logrus.Errorf("Reading container %s STDOUT: %v", cid, err)
}
return err2
}
diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go
deleted file mode 100644
index 4de27d663..000000000
--- a/libpod/oci_conmon_unsupported.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "github.com/containers/common/pkg/config"
-
- "github.com/containers/podman/v3/libpod/define"
-)
-
-const (
- osNotSupported = "Not supported on this OS"
-)
-
-// ConmonOCIRuntime is not supported on this OS.
-type ConmonOCIRuntime struct {
-}
-
-// newConmonOCIRuntime is not supported on this OS.
-func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeFlags []string, runtimeCfg *config.Config) (OCIRuntime, error) {
- return nil, define.ErrNotImplemented
-}
-
-// Name is not supported on this OS.
-func (r *ConmonOCIRuntime) Name() string {
- return osNotSupported
-}
-
-// Path is not supported on this OS.
-func (r *ConmonOCIRuntime) Path() string {
- return osNotSupported
-}
-
-// CreateContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error {
- return define.ErrNotImplemented
-}
-
-// UpdateContainerStatus is not supported on this OS.
-func (r *ConmonOCIRuntime) UpdateContainerStatus(ctr *Container, useRuntime bool) error {
- return define.ErrNotImplemented
-}
-
-// StartContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-// KillContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) KillContainer(ctr *Container, signal uint, all bool) error {
- return define.ErrNotImplemented
-}
-
-// StopContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) StopContainer(ctr *Container, timeout uint, all bool) error {
- return define.ErrNotImplemented
-}
-
-// DeleteContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) DeleteContainer(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-// PauseContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) PauseContainer(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-// UnpauseContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) UnpauseContainer(ctr *Container) error {
- return define.ErrNotImplemented
-}
-
-// ExecContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) ExecContainer(ctr *Container, sessionID string, options *ExecOptions) (int, chan error, error) {
- return -1, nil, define.ErrNotImplemented
-}
-
-// ExecStopContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) ExecStopContainer(ctr *Container, sessionID string, timeout uint) error {
- return define.ErrNotImplemented
-}
-
-// CheckpointContainer is not supported on this OS.
-func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options ContainerCheckpointOptions) error {
- return define.ErrNotImplemented
-}
-
-// SupportsCheckpoint is not supported on this OS.
-func (r *ConmonOCIRuntime) SupportsCheckpoint() bool {
- return false
-}
-
-// SupportsJSONErrors is not supported on this OS.
-func (r *ConmonOCIRuntime) SupportsJSONErrors() bool {
- return false
-}
-
-// SupportsNoCgroups is not supported on this OS.
-func (r *ConmonOCIRuntime) SupportsNoCgroups() bool {
- return false
-}
-
-// AttachSocketPath is not supported on this OS.
-func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) {
- return "", define.ErrNotImplemented
-}
-
-// ExecAttachSocketPath is not supported on this OS.
-func (r *ConmonOCIRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) (string, error) {
- return "", define.ErrNotImplemented
-}
-
-// ExitFilePath is not supported on this OS.
-func (r *ConmonOCIRuntime) ExitFilePath(ctr *Container) (string, error) {
- return "", define.ErrNotImplemented
-}
-
-// RuntimeInfo is not supported on this OS.
-func (r *ConmonOCIRuntime) RuntimeInfo() (*define.ConmonInfo, *define.OCIRuntimeInfo, error) {
- return nil, nil, define.ErrNotImplemented
-}
-
-// Package is not supported on this OS.
-func (r *ConmonOCIRuntime) Package() string {
- return osNotSupported
-}
-
-// ConmonPackage is not supported on this OS.
-func (r *ConmonOCIRuntime) ConmonPackage() string {
- return osNotSupported
-}
diff --git a/libpod/oci_util.go b/libpod/oci_util.go
index 7db267915..c1afc0d20 100644
--- a/libpod/oci_util.go
+++ b/libpod/oci_util.go
@@ -72,7 +72,7 @@ func bindPorts(ports []types.OCICNIPortMapping) ([]*os.File, error) {
// note that this does not affect the fd, see the godoc for server.File()
err = server.Close()
if err != nil {
- logrus.Warnf("failed to close connection: %v", err)
+ logrus.Warnf("Failed to close connection: %v", err)
}
case "tcp":
@@ -106,13 +106,13 @@ func bindPorts(ports []types.OCICNIPortMapping) ([]*os.File, error) {
// note that this does not affect the fd, see the godoc for server.File()
err = server.Close()
if err != nil {
- logrus.Warnf("failed to close connection: %v", err)
+ logrus.Warnf("Failed to close connection: %v", err)
}
case "sctp":
if !notifySCTP {
notifySCTP = true
- logrus.Warnf("port reservation for SCTP is not supported")
+ logrus.Warnf("Port reservation for SCTP is not supported")
}
default:
return nil, fmt.Errorf("unknown protocol %s", i.Protocol)
diff --git a/libpod/options.go b/libpod/options.go
index 3f6ccf1cb..553af43fd 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
+ "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -1113,7 +1114,7 @@ func WithLogDriver(driver string) CtrCreateOption {
switch driver {
case "":
return errors.Wrapf(define.ErrInvalidArg, "log driver must be set")
- case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging:
+ case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging:
break
default:
return errors.Wrapf(define.ErrInvalidArg, "invalid log driver")
@@ -1809,6 +1810,17 @@ func WithInitCtrType(containerType string) CtrCreateOption {
}
}
+// WithHostDevice adds the original host src to the config
+func WithHostDevice(dev []specs.LinuxDevice) CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+ ctr.config.DeviceHostSrc = dev
+ return nil
+ }
+}
+
// Pod Creation Options
// WithPodCreateCommand adds the full command plus arguments of the current
diff --git a/libpod/pod.go b/libpod/pod.go
index e4516b354..c0b0a974b 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -164,8 +164,7 @@ func (p *Pod) PidMode() string {
if err != nil {
return ""
}
- conf := infra.Config()
- ctrSpec := conf.Spec
+ ctrSpec := infra.config.Spec
if ctrSpec != nil && ctrSpec.Linux != nil {
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == specs.PIDNamespace {
@@ -186,8 +185,7 @@ func (p *Pod) UserNSMode() string {
if err != nil {
return ""
}
- conf := infra.Config()
- ctrSpec := conf.Spec
+ ctrSpec := infra.config.Spec
if ctrSpec != nil && ctrSpec.Linux != nil {
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == specs.UserNamespace {
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 4e0acf950..971309f77 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -34,7 +34,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error {
}
// If the container is a once init container, we need to remove it
// after it runs
- if initCon.Config().InitContainerType == define.OneShotInitContainer {
+ if initCon.config.InitContainerType == define.OneShotInitContainer {
icLock := initCon.lock
icLock.Lock()
if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil {
@@ -43,7 +43,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error {
}
// Removing a container this way requires an explicit call to clean up the db
if err := p.runtime.state.RemoveContainerFromPod(p, initCon); err != nil {
- logrus.Errorf("Error removing container %s from database: %v", initCon.ID(), err)
+ logrus.Errorf("Removing container %s from database: %v", initCon.ID(), err)
}
icLock.Unlock()
}
@@ -583,51 +583,58 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
// container.
var infraConfig *define.InspectPodInfraConfig
var inspectMounts []define.InspectMount
+ var devices []define.InspectDevice
if p.state.InfraContainerID != "" {
infra, err := p.runtime.GetContainer(p.state.InfraContainerID)
if err != nil {
return nil, err
}
infraConfig = new(define.InspectPodInfraConfig)
- infraConfig.HostNetwork = !infra.Config().ContainerNetworkConfig.UseImageHosts
- infraConfig.StaticIP = infra.Config().ContainerNetworkConfig.StaticIP
- infraConfig.NoManageResolvConf = infra.Config().UseImageResolvConf
- infraConfig.NoManageHosts = infra.Config().UseImageHosts
+ infraConfig.HostNetwork = !infra.config.ContainerNetworkConfig.UseImageHosts
+ infraConfig.StaticIP = infra.config.ContainerNetworkConfig.StaticIP
+ infraConfig.NoManageResolvConf = infra.config.UseImageResolvConf
+ infraConfig.NoManageHosts = infra.config.UseImageHosts
infraConfig.CPUPeriod = p.CPUPeriod()
infraConfig.CPUQuota = p.CPUQuota()
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
infraConfig.PidNS = p.PidMode()
infraConfig.UserNS = p.UserNSMode()
- namedVolumes, mounts := infra.sortUserVolumes(infra.Config().Spec)
+ namedVolumes, mounts := infra.sortUserVolumes(infra.config.Spec)
inspectMounts, err = infra.GetInspectMounts(namedVolumes, infra.config.ImageVolumes, mounts)
if err != nil {
return nil, err
}
- if len(infra.Config().ContainerNetworkConfig.DNSServer) > 0 {
- infraConfig.DNSServer = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSServer))
- for _, entry := range infra.Config().ContainerNetworkConfig.DNSServer {
+ var nodes map[string]string
+ devices, err = infra.GetDevices(false, *infra.config.Spec, nodes)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(infra.config.ContainerNetworkConfig.DNSServer) > 0 {
+ infraConfig.DNSServer = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSServer))
+ for _, entry := range infra.config.ContainerNetworkConfig.DNSServer {
infraConfig.DNSServer = append(infraConfig.DNSServer, entry.String())
}
}
- if len(infra.Config().ContainerNetworkConfig.DNSSearch) > 0 {
- infraConfig.DNSSearch = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSSearch))
- infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.Config().ContainerNetworkConfig.DNSSearch...)
+ if len(infra.config.ContainerNetworkConfig.DNSSearch) > 0 {
+ infraConfig.DNSSearch = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSSearch))
+ infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.config.ContainerNetworkConfig.DNSSearch...)
}
- if len(infra.Config().ContainerNetworkConfig.DNSOption) > 0 {
- infraConfig.DNSOption = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSOption))
- infraConfig.DNSOption = append(infraConfig.DNSOption, infra.Config().ContainerNetworkConfig.DNSOption...)
+ if len(infra.config.ContainerNetworkConfig.DNSOption) > 0 {
+ infraConfig.DNSOption = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSOption))
+ infraConfig.DNSOption = append(infraConfig.DNSOption, infra.config.ContainerNetworkConfig.DNSOption...)
}
- if len(infra.Config().HostAdd) > 0 {
- infraConfig.HostAdd = make([]string, 0, len(infra.Config().HostAdd))
- infraConfig.HostAdd = append(infraConfig.HostAdd, infra.Config().HostAdd...)
+ if len(infra.config.HostAdd) > 0 {
+ infraConfig.HostAdd = make([]string, 0, len(infra.config.HostAdd))
+ infraConfig.HostAdd = append(infraConfig.HostAdd, infra.config.HostAdd...)
}
- if len(infra.Config().ContainerNetworkConfig.Networks) > 0 {
- infraConfig.Networks = make([]string, 0, len(infra.Config().ContainerNetworkConfig.Networks))
- infraConfig.Networks = append(infraConfig.Networks, infra.Config().ContainerNetworkConfig.Networks...)
+ if len(infra.config.ContainerNetworkConfig.Networks) > 0 {
+ infraConfig.Networks = make([]string, 0, len(infra.config.ContainerNetworkConfig.Networks))
+ infraConfig.Networks = append(infraConfig.Networks, infra.config.ContainerNetworkConfig.Networks...)
}
- infraConfig.NetworkOptions = infra.Config().ContainerNetworkConfig.NetworkOptions
- infraConfig.PortBindings = makeInspectPortBindings(infra.Config().ContainerNetworkConfig.PortMappings, nil)
+ infraConfig.NetworkOptions = infra.config.ContainerNetworkConfig.NetworkOptions
+ infraConfig.PortBindings = makeInspectPortBindings(infra.config.ContainerNetworkConfig.PortMappings, nil)
}
inspectData := define.InspectPodData{
@@ -652,6 +659,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
CPUPeriod: p.CPUPeriod(),
CPUQuota: p.CPUQuota(),
Mounts: inspectMounts,
+ Devices: devices,
}
return &inspectData, nil
diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go
index 079b631a0..d903b8719 100644
--- a/libpod/pod_internal.go
+++ b/libpod/pod_internal.go
@@ -71,7 +71,7 @@ func (p *Pod) refresh() error {
case config.SystemdCgroupsManager:
cgroupPath, err := systemdSliceFromPath(p.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", p.ID()))
if err != nil {
- logrus.Errorf("Error creating CGroup for pod %s: %v", p.ID(), err)
+ logrus.Errorf("Creating CGroup for pod %s: %v", p.ID(), err)
}
p.state.CgroupPath = cgroupPath
case config.CgroupfsCgroupsManager:
diff --git a/libpod/pod_top_unsupported.go b/libpod/pod_top_unsupported.go
deleted file mode 100644
index 59d2ff9a2..000000000
--- a/libpod/pod_top_unsupported.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// +build !linux
-
-package libpod
-
-import "github.com/containers/podman/v3/libpod/define"
-
-// GetPodPidInformation is exclusive to linux
-func (p *Pod) GetPodPidInformation(descriptors []string) ([]string, error) {
- return nil, define.ErrNotImplemented
-}
diff --git a/libpod/reset.go b/libpod/reset.go
index 8e753e845..7b25ed680 100644
--- a/libpod/reset.go
+++ b/libpod/reset.go
@@ -27,7 +27,7 @@ func (r *Runtime) Reset(ctx context.Context) error {
if errors.Cause(err) == define.ErrNoSuchPod {
continue
}
- logrus.Errorf("Error removing Pod %s: %v", p.ID(), err)
+ logrus.Errorf("Removing Pod %s: %v", p.ID(), err)
}
}
@@ -42,13 +42,13 @@ func (r *Runtime) Reset(ctx context.Context) error {
if errors.Cause(err) == define.ErrNoSuchCtr {
continue
}
- logrus.Errorf("Error removing container %s: %v", c.ID(), err)
+ logrus.Errorf("Removing container %s: %v", c.ID(), err)
}
}
}
if err := r.stopPauseProcess(); err != nil {
- logrus.Errorf("Error stopping pause process: %v", err)
+ logrus.Errorf("Stopping pause process: %v", err)
}
rmiOptions := &libimage.RemoveImagesOptions{Filters: []string{"readonly=false"}}
@@ -65,7 +65,7 @@ func (r *Runtime) Reset(ctx context.Context) error {
if errors.Cause(err) == define.ErrNoSuchVolume {
continue
}
- logrus.Errorf("Error removing volume %s: %v", v.config.Name, err)
+ logrus.Errorf("Removing volume %s: %v", v.config.Name, err)
}
}
@@ -123,7 +123,7 @@ func (r *Runtime) Reset(ctx context.Context) error {
if storageConfPath, err := storage.DefaultConfigFile(rootless.IsRootless()); err == nil {
if _, err = os.Stat(storageConfPath); err == nil {
fmt.Printf("A storage.conf file exists at %s\n", storageConfPath)
- fmt.Println("You should remove this file if you did not modified the configuration.")
+ fmt.Println("You should remove this file if you did not modify the configuration.")
}
} else {
if prevError != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index a2279e56d..27885bf5c 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -211,7 +211,7 @@ func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...R
os.Exit(1)
return nil
}); err != nil && errors.Cause(err) != shutdown.ErrHandlerExists {
- logrus.Errorf("Error registering shutdown handler for libpod: %v", err)
+ logrus.Errorf("Registering shutdown handler for libpod: %v", err)
}
if err := shutdown.Start(); err != nil {
@@ -344,7 +344,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
logrus.Warn(msg)
}
} else {
- logrus.Warn(msg)
+ logrus.Warnf("%s: %v", msg, err)
}
}
}
@@ -388,7 +388,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// Don't forcibly shut down
// We could be opening a store in use by another libpod
if _, err := store.Shutdown(false); err != nil {
- logrus.Errorf("Error removing store for partially-created runtime: %s", err)
+ logrus.Errorf("Removing store for partially-created runtime: %s", err)
}
}
}()
@@ -436,7 +436,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// This will allow us to ship configs including optional
// runtimes that might not be installed (crun, kata).
// Only a infof so default configs don't spec errors.
- logrus.Debugf("configured OCI runtime %s initialization failed: %v", name, err)
+ logrus.Debugf("Configured OCI runtime %s initialization failed: %v", name, err)
continue
}
@@ -706,19 +706,32 @@ func (r *Runtime) TmpDir() (string, error) {
return r.config.Engine.TmpDir, nil
}
-// GetConfig returns a copy of the configuration used by the runtime
-func (r *Runtime) GetConfig() (*config.Config, error) {
+// GetConfig returns the configuration used by the runtime.
+// Note that the returned value is not a copy and must hence
+// only be used in a reading fashion.
+func (r *Runtime) GetConfigNoCopy() (*config.Config, error) {
r.lock.RLock()
defer r.lock.RUnlock()
if !r.valid {
return nil, define.ErrRuntimeStopped
}
+ return r.config, nil
+}
+
+// GetConfig returns a copy of the configuration used by the runtime.
+// Please use GetConfigNoCopy() in case you only want to read from
+// but not write to the returned config.
+func (r *Runtime) GetConfig() (*config.Config, error) {
+ rtConfig, err := r.GetConfigNoCopy()
+ if err != nil {
+ return nil, err
+ }
config := new(config.Config)
// Copy so the caller won't be able to modify the actual config
- if err := JSONDeepCopy(r.config, config); err != nil {
+ if err := JSONDeepCopy(rtConfig, config); err != nil {
return nil, errors.Wrapf(err, "error copying config")
}
@@ -767,7 +780,7 @@ func (r *Runtime) libimageEvents() {
Type: events.Image,
}
if err := r.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write image event: %q", err)
+ logrus.Errorf("Unable to write image event: %q", err)
}
}
@@ -807,11 +820,11 @@ func (r *Runtime) Shutdown(force bool) error {
if force {
ctrs, err := r.state.AllContainers()
if err != nil {
- logrus.Errorf("Error retrieving containers from database: %v", err)
+ logrus.Errorf("Retrieving containers from database: %v", err)
} else {
for _, ctr := range ctrs {
if err := ctr.StopWithTimeout(r.config.Engine.StopTimeout); err != nil {
- logrus.Errorf("Error stopping container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Stopping container %s: %v", ctr.ID(), err)
}
}
}
@@ -833,7 +846,7 @@ func (r *Runtime) Shutdown(force bool) error {
}
if err := r.state.Close(); err != nil {
if lastError != nil {
- logrus.Errorf("%v", lastError)
+ logrus.Error(lastError)
}
lastError = err
}
@@ -879,17 +892,17 @@ func (r *Runtime) refresh(alivePath string) error {
// until this has run.
for _, ctr := range ctrs {
if err := ctr.refresh(); err != nil {
- logrus.Errorf("Error refreshing container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Refreshing container %s: %v", ctr.ID(), err)
}
}
for _, pod := range pods {
if err := pod.refresh(); err != nil {
- logrus.Errorf("Error refreshing pod %s: %v", pod.ID(), err)
+ logrus.Errorf("Refreshing pod %s: %v", pod.ID(), err)
}
}
for _, vol := range vols {
if err := vol.refresh(); err != nil {
- logrus.Errorf("Error refreshing volume %s: %v", vol.Name(), err)
+ logrus.Errorf("Refreshing volume %s: %v", vol.Name(), err)
}
}
@@ -1099,7 +1112,7 @@ func (r *Runtime) reloadContainersConf() error {
return err
}
r.config = config
- logrus.Infof("applied new containers configuration: %v", config)
+ logrus.Infof("Applied new containers configuration: %v", config)
return nil
}
@@ -1110,7 +1123,7 @@ func (r *Runtime) reloadStorageConf() error {
return err
}
storage.ReloadConfigurationFile(configFile, &r.storageConfig)
- logrus.Infof("applied new storage configuration: %v", r.storageConfig)
+ logrus.Infof("Applied new storage configuration: %v", r.storageConfig)
return nil
}
diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go
index cd2f226af..5694967aa 100644
--- a/libpod/runtime_cstorage.go
+++ b/libpod/runtime_cstorage.go
@@ -106,22 +106,22 @@ func (r *Runtime) removeStorageContainer(idOrName string, force bool) error {
logrus.Infof("Storage for container %s already removed", ctr.ID)
return nil
}
- return errors.Wrapf(err, "error looking up container %q mounts", idOrName)
+ logrus.Warnf("Checking if container %q is mounted, attempting to delete: %v", idOrName, err)
}
if timesMounted > 0 {
return errors.Wrapf(define.ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName)
}
} else if _, err := r.store.Unmount(ctr.ID, true); err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
+ if errors.Is(err, storage.ErrContainerUnknown) {
// Container again gone, no error
logrus.Infof("Storage for container %s already removed", ctr.ID)
return nil
}
- return errors.Wrapf(err, "error unmounting container %q", idOrName)
+ logrus.Warnf("Unmounting container %q while attempting to delete storage: %v", idOrName, err)
}
if err := r.store.DeleteContainer(ctr.ID); err != nil {
- if errors.Cause(err) == storage.ErrContainerUnknown {
+ if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown {
// Container again gone, no error
logrus.Infof("Storage for container %s already removed", ctr.ID)
return nil
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index d4f67a115..00979a500 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -59,7 +59,7 @@ func (r *Runtime) PrepareVolumeOnCreateContainer(ctx context.Context, ctr *Conta
defer func() {
if err := ctr.cleanupStorage(); err != nil {
- logrus.Errorf("error cleaning up container storage %s: %v", ctr.ID(), err)
+ logrus.Errorf("Cleaning up container storage %s: %v", ctr.ID(), err)
}
}()
@@ -69,7 +69,7 @@ func (r *Runtime) PrepareVolumeOnCreateContainer(ctx context.Context, ctr *Conta
ctr.state.Mounted = true
ctr.state.Mountpoint = mountPoint
if err = ctr.save(); err != nil {
- logrus.Errorf("Error saving container %s state: %v", ctr.ID(), err)
+ logrus.Errorf("Saving container %s state: %v", ctr.ID(), err)
}
}
@@ -193,10 +193,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
ctr.config.LogPath = ""
}
- ctr.config.Spec = new(spec.Spec)
- if err := JSONDeepCopy(rSpec, ctr.config.Spec); err != nil {
- return nil, errors.Wrapf(err, "error copying runtime spec while creating container")
- }
+ ctr.config.Spec = rSpec
ctr.config.CreatedTime = time.Now()
ctr.state.BindMounts = make(map[string]string)
@@ -234,13 +231,6 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
}
func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Container, retErr error) {
- // Validate the container
- if err := ctr.validate(); err != nil {
- return nil, err
- }
- if ctr.config.IsInfra {
- ctr.config.StopTimeout = 10
- }
// normalize the networks to names
// ocicni only knows about cni names so we have to make
// sure we do not use ids internally
@@ -265,11 +255,26 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if err != nil {
return nil, err
}
+ 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)
+ }
netAliases[netName] = aliases
}
ctr.config.NetworkAliases = netAliases
}
+ // Validate the container
+ if err := ctr.validate(); err != nil {
+ return nil, err
+ }
+ if ctr.config.IsInfra {
+ ctr.config.StopTimeout = 10
+ }
+
// Inhibit shutdown until creation succeeds
shutdown.Inhibit()
defer shutdown.Uninhibit()
@@ -286,7 +291,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
defer func() {
if retErr != nil {
if err := ctr.lock.Free(); err != nil {
- logrus.Errorf("Error freeing lock for container after creation failed: %v", err)
+ logrus.Errorf("Freeing lock for container after creation failed: %v", err)
}
}
}()
@@ -409,7 +414,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
defer func() {
if retErr != nil {
if err := ctr.teardownStorage(); err != nil {
- logrus.Errorf("Error removing partially-created container root filesystem: %s", err)
+ logrus.Errorf("Removing partially-created container root filesystem: %s", err)
}
}
}()
@@ -473,7 +478,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
}
switch ctr.config.LogDriver {
- case define.NoLogging:
+ case define.NoLogging, define.PassthroughLogging:
break
case define.JournaldLogging:
ctr.initializeJournal(ctx)
@@ -696,7 +701,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
if cleanupErr == nil {
cleanupErr = err
} else {
- logrus.Errorf("cleanup storage: %v", err)
+ logrus.Errorf("Cleanup storage: %v", err)
}
}
@@ -709,7 +714,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
if cleanupErr == nil {
cleanupErr = err
} else {
- logrus.Errorf("Error removing container %s from database: %v", c.ID(), err)
+ logrus.Errorf("Removing container %s from database: %v", c.ID(), err)
}
}
}
@@ -718,7 +723,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
if cleanupErr == nil {
cleanupErr = err
} else {
- logrus.Errorf("Error removing container %s from database: %v", c.ID(), err)
+ logrus.Errorf("Removing container %s from database: %v", c.ID(), err)
}
}
}
@@ -728,7 +733,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
if cleanupErr == nil {
cleanupErr = errors.Wrapf(err, "error freeing lock for container %s", c.ID())
} else {
- logrus.Errorf("free container lock: %v", err)
+ logrus.Errorf("Free container lock: %v", err)
}
}
@@ -747,7 +752,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
continue
}
if err := runtime.removeVolume(ctx, volume, false); err != nil && errors.Cause(err) != define.ErrNoSuchVolume {
- logrus.Errorf("cleanup volume (%s): %v", v, err)
+ logrus.Errorf("Cleanup volume (%s): %v", v, err)
}
}
}
@@ -888,7 +893,7 @@ func (r *Runtime) evictContainer(ctx context.Context, idOrName string, removeVol
continue
}
if err := r.removeVolume(ctx, volume, false); err != nil && err != define.ErrNoSuchVolume && err != define.ErrVolumeBeingUsed {
- logrus.Errorf("cleanup volume (%s): %v", v, err)
+ logrus.Errorf("Cleanup volume (%s): %v", v, err)
}
}
}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index a42f9a365..1915a5c4d 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -48,13 +48,34 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage
}
}
+// IsExternalContainerCallback returns a callback that be used in `libimage` to
+// figure out whether a given container is an external one. A container is
+// considered external if it is not present in libpod's database.
+func (r *Runtime) IsExternalContainerCallback(_ context.Context) libimage.IsExternalContainerFunc {
+ // NOTE: pruning external containers is subject to race conditions
+ // (e.g., when a container gets removed). To address this and similar
+ // races, pruning had to happen inside c/storage. Containers has to be
+ // labelled with "podman/libpod" along with callbacks similar to
+ // libimage.
+ return func(idOrName string) (bool, error) {
+ _, err := r.LookupContainer(idOrName)
+ if err == nil {
+ return false, nil
+ }
+ if errors.Is(err, define.ErrNoSuchCtr) {
+ return true, nil
+ }
+ return false, nil
+ }
+}
+
// newBuildEvent creates a new event based on completion of a built image
func (r *Runtime) newImageBuildCompleteEvent(idOrName string) {
e := events.NewEvent(events.Build)
e.Type = events.Image
e.Name = idOrName
if err := r.eventer.Write(e); err != nil {
- logrus.Errorf("unable to write build event: %q", err)
+ logrus.Errorf("Unable to write build event: %q", err)
}
}
diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go
index 3e63bc19e..087991e6f 100644
--- a/libpod/runtime_migrate.go
+++ b/libpod/runtime_migrate.go
@@ -56,7 +56,7 @@ func (r *Runtime) migrate(ctx context.Context) error {
return err
}
- logrus.Infof("stopping all containers")
+ logrus.Infof("Stopping all containers")
for _, ctr := range runningContainers {
fmt.Printf("stopped %s\n", ctr.ID())
if err := ctr.Stop(); err != nil {
@@ -77,7 +77,7 @@ func (r *Runtime) migrate(ctx context.Context) error {
// Reset pause process location
oldLocation := filepath.Join(ctr.state.RunDir, "conmon.pid")
if ctr.config.ConmonPidFile == oldLocation {
- logrus.Infof("changing conmon PID file for %s", ctr.ID())
+ logrus.Infof("Changing conmon PID file for %s", ctr.ID())
ctr.config.ConmonPidFile = filepath.Join(ctr.config.StaticDir, "conmon.pid")
needsWrite = true
}
diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go
deleted file mode 100644
index a9d351318..000000000
--- a/libpod/runtime_migrate_unsupported.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
-)
-
-func (r *Runtime) migrate(ctx context.Context) error {
- return nil
-}
-
-func (r *Runtime) stopPauseProcess() error {
- return nil
-}
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 7571fdfff..5036dd680 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -66,7 +66,7 @@ func (r *Runtime) NewPod(ctx context.Context, p specgen.PodSpecGenerator, option
defer func() {
if deferredErr != nil {
if err := pod.lock.Free(); err != nil {
- logrus.Errorf("Error freeing pod lock after failed creation: %v", err)
+ logrus.Errorf("Freeing pod lock after failed creation: %v", err)
}
}
}()
@@ -224,7 +224,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
conmonCgroup, err := cgroups.Load(conmonCgroupPath)
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
- logrus.Errorf("Error retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ logrus.Errorf("Retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
}
// New resource limits
@@ -259,7 +259,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = err
} else {
- logrus.Errorf("Error removing container %s from pod %s: %v", ctr.ID(), p.ID(), err)
+ logrus.Errorf("Removing container %s from pod %s: %v", ctr.ID(), p.ID(), err)
}
}
}
@@ -275,7 +275,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
for volName := range ctrNamedVolumes {
volume, err := r.state.Volume(volName)
if err != nil && errors.Cause(err) != define.ErrNoSuchVolume {
- logrus.Errorf("Error retrieving volume %s: %v", volName, err)
+ logrus.Errorf("Retrieving volume %s: %v", volName, err)
continue
}
if !volume.Anonymous() {
@@ -285,7 +285,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if errors.Cause(err) == define.ErrNoSuchVolume || errors.Cause(err) == define.ErrVolumeRemoved {
continue
}
- logrus.Errorf("Error removing volume %s: %v", volName, err)
+ logrus.Errorf("Removing volume %s: %v", volName, err)
}
}
@@ -299,7 +299,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID())
} else {
- logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
}
}
case config.CgroupfsCgroupsManager:
@@ -321,7 +321,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID())
} else {
- logrus.Errorf("Error deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ logrus.Errorf("Deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
}
}
}
@@ -330,7 +330,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = errors.Wrapf(err, "error retrieving pod %s cgroup", p.ID())
} else {
- logrus.Errorf("Error retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ logrus.Errorf("Retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
}
}
if err == nil {
@@ -338,7 +338,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID())
} else {
- logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ logrus.Errorf("Deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
}
}
}
@@ -371,7 +371,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if removalErr == nil {
removalErr = errors.Wrapf(err, "error freeing pod %s lock", p.ID())
} else {
- logrus.Errorf("Error freeing pod %s lock: %v", p.ID(), err)
+ logrus.Errorf("Freeing pod %s lock: %v", p.ID(), err)
}
}
diff --git a/libpod/runtime_pod_unsupported.go b/libpod/runtime_pod_unsupported.go
deleted file mode 100644
index 6dbcc9214..000000000
--- a/libpod/runtime_pod_unsupported.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
-
- "github.com/containers/podman/v3/libpod/define"
-)
-
-// NewPod makes a new, empty pod
-func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (*Pod, error) {
- return nil, define.ErrOSNotSupported
-}
-
-func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) error {
- return define.ErrOSNotSupported
-}
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index d1ea7d4fd..def6ca411 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -140,7 +140,7 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
defer func() {
if deferredErr != nil {
if err := volume.lock.Free(); err != nil {
- logrus.Errorf("Error freeing volume lock after failed creation: %v", err)
+ logrus.Errorf("Freeing volume lock after failed creation: %v", err)
}
}
}()
@@ -246,7 +246,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
// If force is set, evict the volume, even if errors
// occur. Otherwise we'll never be able to get rid of
// them.
- logrus.Errorf("Error unmounting volume %s: %v", v.Name(), err)
+ logrus.Errorf("Unmounting volume %s: %v", v.Name(), err)
} else {
return errors.Wrapf(err, "error unmounting volume %s", v.Name())
}
@@ -290,7 +290,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
// Remove the volume from the state
if err := r.state.RemoveVolume(v); err != nil {
if removalErr != nil {
- logrus.Errorf("Error removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr)
+ logrus.Errorf("Removing volume %s from plugin %s: %v", v.Name(), v.Driver(), removalErr)
}
return errors.Wrapf(err, "error removing volume %s", v.Name())
}
@@ -300,7 +300,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
if removalErr == nil {
removalErr = errors.Wrapf(err, "error freeing lock for volume %s", v.Name())
} else {
- logrus.Errorf("Error freeing lock for volume %q: %v", v.Name(), err)
+ logrus.Errorf("Freeing lock for volume %q: %v", v.Name(), err)
}
}
@@ -310,7 +310,7 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
if removalErr == nil {
removalErr = errors.Wrapf(err, "error cleaning up volume storage for %q", v.Name())
} else {
- logrus.Errorf("Error cleaning up volume storage for volume %q: %v", v.Name(), err)
+ logrus.Errorf("Cleaning up volume storage for volume %q: %v", v.Name(), err)
}
}
diff --git a/libpod/runtime_volume_unsupported.go b/libpod/runtime_volume_unsupported.go
deleted file mode 100644
index da7ee3552..000000000
--- a/libpod/runtime_volume_unsupported.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "context"
-
- "github.com/containers/podman/v3/libpod/define"
-)
-
-func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error {
- return define.ErrNotImplemented
-}
-
-func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) {
- return nil, define.ErrNotImplemented
-}
-
-func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) {
- return nil, define.ErrNotImplemented
-}
diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go
index 1e8a9ec3b..cca74c3c4 100644
--- a/libpod/shutdown/handler.go
+++ b/libpod/shutdown/handler.go
@@ -61,7 +61,7 @@ func Start() error {
}
logrus.Infof("Invoking shutdown handler %s", name)
if err := handler(sig); err != nil {
- logrus.Errorf("Error running shutdown handler %s: %v", name, err)
+ logrus.Errorf("Running shutdown handler %s: %v", name, err)
}
}
handlerLock.Unlock()
diff --git a/libpod/stats_unsupported.go b/libpod/stats_unsupported.go
deleted file mode 100644
index 44a1c8d03..000000000
--- a/libpod/stats_unsupported.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// +build !linux
-
-package libpod
-
-import "github.com/containers/podman/v3/libpod/define"
-
-// GetContainerStats gets the running stats for a given container
-func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*define.ContainerStats, error) {
- return nil, define.ErrOSNotSupported
-}
diff --git a/libpod/storage.go b/libpod/storage.go
index 4aa42dc8e..5c265df40 100644
--- a/libpod/storage.go
+++ b/libpod/storage.go
@@ -118,22 +118,22 @@ func (r *storageService) CreateContainerStorage(ctx context.Context, systemConte
container, err := r.store.CreateContainer(containerID, names, imageID, "", string(mdata), &options)
if err != nil {
- logrus.Debugf("failed to create container %s(%s): %v", metadata.ContainerName, containerID, err)
+ logrus.Debugf("Failed to create container %s(%s): %v", metadata.ContainerName, containerID, err)
return ContainerInfo{}, err
}
- logrus.Debugf("created container %q", container.ID)
+ logrus.Debugf("Created container %q", container.ID)
// If anything fails after this point, we need to delete the incomplete
// container before returning.
defer func() {
if retErr != nil {
if err := r.store.DeleteContainer(container.ID); err != nil {
- logrus.Infof("%v deleting partially-created container %q", err, container.ID)
+ logrus.Infof("Error deleting partially-created container %q: %v", container.ID, err)
return
}
- logrus.Infof("deleted partially-created container %q", container.ID)
+ logrus.Infof("Deleted partially-created container %q", container.ID)
}
}()
@@ -155,13 +155,13 @@ func (r *storageService) CreateContainerStorage(ctx context.Context, systemConte
if err != nil {
return ContainerInfo{}, err
}
- logrus.Debugf("container %q has work directory %q", container.ID, containerDir)
+ logrus.Debugf("Container %q has work directory %q", container.ID, containerDir)
containerRunDir, err := r.store.ContainerRunDirectory(container.ID)
if err != nil {
return ContainerInfo{}, err
}
- logrus.Debugf("container %q has run directory %q", container.ID, containerRunDir)
+ logrus.Debugf("Container %q has run directory %q", container.ID, containerRunDir)
return ContainerInfo{
UIDMap: options.UIDMap,
@@ -184,8 +184,12 @@ func (r *storageService) DeleteContainer(idOrName string) error {
}
err = r.store.DeleteContainer(container.ID)
if err != nil {
- logrus.Debugf("failed to delete container %q: %v", container.ID, err)
- return err
+ if errors.Cause(err) == storage.ErrNotAContainer || errors.Cause(err) == storage.ErrContainerUnknown {
+ logrus.Infof("Storage for container %s already removed", container.ID)
+ } else {
+ logrus.Debugf("Failed to delete container %q: %v", container.ID, err)
+ return err
+ }
}
return nil
}
@@ -193,7 +197,7 @@ func (r *storageService) DeleteContainer(idOrName string) error {
func (r *storageService) SetContainerMetadata(idOrName string, metadata RuntimeContainerMetadata) error {
mdata, err := json.Marshal(&metadata)
if err != nil {
- logrus.Debugf("failed to encode metadata for %q: %v", idOrName, err)
+ logrus.Debugf("Failed to encode metadata for %q: %v", idOrName, err)
return err
}
return r.store.SetMetadata(idOrName, string(mdata))
@@ -225,10 +229,10 @@ func (r *storageService) MountContainerImage(idOrName string) (string, error) {
}
mountPoint, err := r.store.Mount(container.ID, metadata.MountLabel)
if err != nil {
- logrus.Debugf("failed to mount container %q: %v", container.ID, err)
+ logrus.Debugf("Failed to mount container %q: %v", container.ID, err)
return "", err
}
- logrus.Debugf("mounted container %q at %q", container.ID, mountPoint)
+ logrus.Debugf("Mounted container %q at %q", container.ID, mountPoint)
return mountPoint, nil
}
@@ -252,10 +256,10 @@ func (r *storageService) UnmountContainerImage(idOrName string, force bool) (boo
}
mounted, err := r.store.Unmount(container.ID, force)
if err != nil {
- logrus.Debugf("failed to unmount container %q: %v", container.ID, err)
+ logrus.Debugf("Failed to unmount container %q: %v", container.ID, err)
return false, err
}
- logrus.Debugf("unmounted container %q", container.ID)
+ logrus.Debugf("Unmounted container %q", container.ID)
return mounted, nil
}
diff --git a/libpod/util.go b/libpod/util.go
index d3f7da91e..8f8303ff2 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -240,14 +240,14 @@ func hijackWriteError(toWrite error, cid string, terminal bool, httpBuf *bufio.R
// We need a header.
header := makeHTTPAttachHeader(2, uint32(len(errString)))
if _, err := httpBuf.Write(header); err != nil {
- logrus.Errorf("Error writing header for container %s attach connection error: %v", cid, err)
+ logrus.Errorf("Writing header for container %s attach connection error: %v", cid, err)
}
}
if _, err := httpBuf.Write(errString); err != nil {
- logrus.Errorf("Error writing error to container %s HTTP attach connection: %v", cid, err)
+ logrus.Errorf("Writing error to container %s HTTP attach connection: %v", cid, err)
}
if err := httpBuf.Flush(); err != nil {
- logrus.Errorf("Error flushing HTTP buffer for container %s HTTP attach connection: %v", cid, err)
+ logrus.Errorf("Flushing HTTP buffer for container %s HTTP attach connection: %v", cid, err)
}
}
}
@@ -259,7 +259,7 @@ func hijackWriteErrorAndClose(toWrite error, cid string, terminal bool, httpCon
hijackWriteError(toWrite, cid, terminal, httpBuf)
if err := httpCon.Close(); err != nil {
- logrus.Errorf("Error closing container %s HTTP attach connection: %v", cid, err)
+ logrus.Errorf("Closing container %s HTTP attach connection: %v", cid, err)
}
}
diff --git a/libpod/util_linux.go b/libpod/util_linux.go
index 32b058d27..e2ea97185 100644
--- a/libpod/util_linux.go
+++ b/libpod/util_linux.go
@@ -119,7 +119,7 @@ func LabelVolumePath(path string) error {
func Unmount(mount string) {
if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil {
if err != syscall.EINVAL {
- logrus.Warnf("failed to unmount %s : %v", mount, err)
+ logrus.Warnf("Failed to unmount %s : %v", mount, err)
} else {
logrus.Debugf("failed to unmount %s : %v", mount, err)
}
diff --git a/libpod/util_unsupported.go b/libpod/util_unsupported.go
deleted file mode 100644
index b718d36aa..000000000
--- a/libpod/util_unsupported.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "github.com/containers/podman/v3/libpod/define"
- "github.com/pkg/errors"
-)
-
-func systemdSliceFromPath(parent, name string) (string, error) {
- return "", errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes")
-}
-
-func makeSystemdCgroup(path string) error {
- return errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes")
-}
-
-func deleteSystemdCgroup(path string) error {
- return errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes")
-}
-
-func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) {
- return "", errors.Wrapf(define.ErrOSNotSupported, "cgroups are not supported on non-linux OSes")
-}
-
-// LabelVolumePath takes a mount path for a volume and gives it an
-// selinux label of either shared or not
-func LabelVolumePath(path string) error {
- return define.ErrNotImplemented
-}
-
-func Unmount(mount string) error {
- return define.ErrNotImplemented
-}
diff --git a/libpod/volume_internal_unsupported.go b/libpod/volume_internal_unsupported.go
deleted file mode 100644
index 77452cf22..000000000
--- a/libpod/volume_internal_unsupported.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// +build !linux
-
-package libpod
-
-import (
- "github.com/containers/podman/v3/libpod/define"
-)
-
-func (v *Volume) mount() error {
- return define.ErrNotImplemented
-}
-
-func (v *Volume) unmount(force bool) error {
- return define.ErrNotImplemented
-}
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index a15fdb553..18005e24a 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -410,11 +410,11 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
if l.HasHealthCheck() && state.Status != "created" {
state.Health = &types.Health{
- Status: inspect.State.Healthcheck.Status,
- FailingStreak: inspect.State.Healthcheck.FailingStreak,
+ Status: inspect.State.Health.Status,
+ FailingStreak: inspect.State.Health.FailingStreak,
}
- log := inspect.State.Healthcheck.Log
+ log := inspect.State.Health.Log
for _, item := range log {
res := &types.HealthcheckResult{}
diff --git a/pkg/api/handlers/compat/containers_start.go b/pkg/api/handlers/compat/containers_start.go
index ca2b5d84c..fb68389bc 100644
--- a/pkg/api/handlers/compat/containers_start.go
+++ b/pkg/api/handlers/compat/containers_start.go
@@ -25,7 +25,7 @@ func StartContainer(w http.ResponseWriter, r *http.Request) {
}
if len(query.DetachKeys) > 0 {
// TODO - start does not support adding detach keys
- logrus.Info("the detach keys parameter is not supported on start container")
+ logrus.Info("The detach keys parameter is not supported on start container")
}
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index e872f885a..0051e7235 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -227,10 +227,10 @@ func toBlkioStatEntry(entries []cgroups.BlkIOEntry) []docker.BlkioStatEntry {
for i, e := range entries {
bits, err := json.Marshal(e)
if err != nil {
- logrus.Errorf("unable to marshal blkio stats: %q", err)
+ logrus.Errorf("Unable to marshal blkio stats: %q", err)
}
if err := json.Unmarshal(bits, &results[i]); err != nil {
- logrus.Errorf("unable to unmarshal blkio stats: %q", err)
+ logrus.Errorf("Unable to unmarshal blkio stats: %q", err)
}
}
return results
diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go
index a79b33ecc..901acdac4 100644
--- a/pkg/api/handlers/compat/events.go
+++ b/pkg/api/handlers/compat/events.go
@@ -94,7 +94,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
}
if err := coder.Encode(e); err != nil {
- logrus.Errorf("unable to write json: %q", err)
+ logrus.Errorf("Unable to write json: %q", err)
}
flush()
case <-r.Context().Done():
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index b4f08a746..1c6cc917c 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -150,7 +150,8 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- All bool `schema:"all"`
+ All bool `schema:"all"`
+ External bool `schema:"external"`
}{
// override any golang type defaults
}
@@ -190,8 +191,9 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
pruneOptions := entities.ImagePruneOptions{
- All: query.All,
- Filter: libpodFilters,
+ All: query.All,
+ External: query.External,
+ Filter: libpodFilters,
}
imagePruneReports, err := imageEngine.Prune(r.Context(), pruneOptions)
if err != nil {
@@ -289,9 +291,10 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Compress bool `schema:"compress"`
- Format string `schema:"format"`
- References []string `schema:"references"`
+ Compress bool `schema:"compress"`
+ Format string `schema:"format"`
+ OciAcceptUncompressedLayers bool `schema:"ociAcceptUncompressedLayers"`
+ References []string `schema:"references"`
}{
Format: define.OCIArchive,
}
@@ -353,11 +356,11 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
// Use the ABI image engine to share as much code as possible.
opts := entities.ImageSaveOptions{
- Compress: query.Compress,
- Format: query.Format,
- MultiImageArchive: len(query.References) > 1,
- Output: output,
- RemoveSignatures: true,
+ Compress: query.Compress,
+ Format: query.Format,
+ MultiImageArchive: len(query.References) > 1,
+ OciAcceptUncompressedLayers: query.OciAcceptUncompressedLayers,
+ Output: output,
}
imageEngine := abi.ImageEngine{Libpod: runtime}
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 1f03e121e..7bd6d3dbf 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -41,8 +41,8 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
return
}
if !psg.NoInfra {
- infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}} // options for pulling the image and FillOutSpec
- err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
+ infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}, Devices: psg.Devices} // options for pulling the image and FillOutSpec
+ 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"))
return
@@ -186,9 +186,9 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
// Try to clean up the pod - but only warn on failure, it's nonfatal.
if cleanupCtrs, cleanupErr := pod.Cleanup(r.Context()); cleanupErr != nil {
- logrus.Errorf("Error cleaning up pod %s: %v", pod.ID(), cleanupErr)
+ logrus.Errorf("Cleaning up pod %s: %v", pod.ID(), cleanupErr)
for id, err := range cleanupCtrs {
- logrus.Errorf("Error cleaning up pod %s container %s: %v", pod.ID(), id, err)
+ logrus.Errorf("Cleaning up pod %s container %s: %v", pod.ID(), id, err)
}
}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index b82c586ea..fedab3bb3 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -183,7 +183,8 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) {
}
is := entities.ImageSummary{
- ID: l.ID(),
+ // docker adds sha256: in front of the ID
+ ID: "sha256:" + l.ID(),
ParentId: imageData.Parent,
RepoTags: imageData.RepoTags,
RepoDigests: imageData.RepoDigests,
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index 5cdb31de1..6f875fc30 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -78,7 +78,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) {
exitCode, err := waitDockerCondition(ctx, name, interval, condition)
var errStruct *struct{ Message string }
if err != nil {
- logrus.Errorf("error while waiting on condition: %q", err)
+ logrus.Errorf("While waiting on condition: %q", err)
errStruct = &struct {
Message string
}{
@@ -94,7 +94,7 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) {
enc.SetEscapeHTML(true)
err = enc.Encode(&responseData)
if err != nil {
- logrus.Errorf("unable to write json: %q", err)
+ logrus.Errorf("Unable to write json: %q", err)
}
}
diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go
index 7625f9546..29139a98e 100644
--- a/pkg/api/handlers/utils/handler.go
+++ b/pkg/api/handlers/utils/handler.go
@@ -89,21 +89,21 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
w.WriteHeader(code)
if _, err := fmt.Fprintln(w, v); err != nil {
- logrus.Errorf("unable to send string response: %q", err)
+ logrus.Errorf("Unable to send string response: %q", err)
}
case *os.File:
w.Header().Set("Content-Type", "application/octet; charset=us-ascii")
w.WriteHeader(code)
if _, err := io.Copy(w, v); err != nil {
- logrus.Errorf("unable to copy to response: %q", err)
+ logrus.Errorf("Unable to copy to response: %q", err)
}
case io.Reader:
w.Header().Set("Content-Type", "application/x-tar")
w.WriteHeader(code)
if _, err := io.Copy(w, v); err != nil {
- logrus.Errorf("unable to copy to response: %q", err)
+ logrus.Errorf("Unable to copy to response: %q", err)
}
default:
WriteJSON(w, code, value)
@@ -162,7 +162,7 @@ func WriteJSON(w http.ResponseWriter, code int, value interface{}) {
coder := json.NewEncoder(w)
coder.SetEscapeHTML(true)
if err := coder.Encode(value); err != nil {
- logrus.Errorf("unable to write json: %q", err)
+ logrus.Errorf("Unable to write json: %q", err)
}
}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 95981226c..aa573eaa6 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -176,6 +176,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - in: query
// name: limit
// type: integer
+ // default: 25
// description: maximum number of results
// - in: query
// name: filters
@@ -186,6 +187,11 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - `is-official=(true|false)`
// - `stars=<number>` Matches images that has at least 'number' stars.
// - in: query
+ // name: tlsVerify
+ // type: boolean
+ // default: false
+ // description: skip TLS verification for registries
+ // - in: query
// name: listTags
// type: boolean
// description: list the available tags in the repository
@@ -1044,6 +1050,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: |
// Remove all images not in use by containers, not just dangling ones
// - in: query
+ // name: external
+ // default: false
+ // type: boolean
+ // description: |
+ // Remove images even when they are used by external containers (e.g, by build containers)
+ // - in: query
// name: filters
// type: string
// description: |
@@ -1075,6 +1087,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - in: query
// name: limit
// type: integer
+ // default: 25
// description: maximum number of results
// - in: query
// name: noTrunc
@@ -1088,6 +1101,16 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - `is-automated=(true|false)`
// - `is-official=(true|false)`
// - `stars=<number>` Matches images that has at least 'number' stars.
+ // - in: query
+ // name: tlsVerify
+ // type: boolean
+ // default: false
+ // description: skip TLS verification for registries
+ // - in: query
+ // name: listTags
+ // type: boolean
+ // default: false
+ // description: list the available tags in the repository
// produces:
// - application/json
// responses:
@@ -1150,6 +1173,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// name: compress
// type: boolean
// description: use compression on image
+ // - in: query
+ // name: ociAcceptUncompressedLayers
+ // type: boolean
+ // description: accept uncompressed layers when copying OCI images
// produces:
// - application/json
// responses:
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 34d0fa246..c7174775e 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -233,7 +233,7 @@ func (s *APIServer) Serve() error {
s.pprof = &http.Server{Addr: "localhost:8888", Handler: pprofMux}
err := s.pprof.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
- logrus.Warn("API profiler service failed: " + err.Error())
+ logrus.Warnf("API profiler service failed: %v", err)
}
}()
}
@@ -272,7 +272,7 @@ func (s *APIServer) Shutdown() error {
go func() {
defer cancel()
if err := s.pprof.Shutdown(ctx); err != nil {
- logrus.Warn("Failed to cleanly shutdown API pprof service: " + err.Error())
+ logrus.Warnf("Failed to cleanly shutdown API pprof service: %v", err)
}
}()
<-ctx.Done()
diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go
index 6aff880f4..070e222ad 100644
--- a/pkg/auth/auth.go
+++ b/pkg/auth/auth.go
@@ -208,7 +208,7 @@ func RemoveAuthfile(authfile string) {
return
}
if err := os.Remove(authfile); err != nil {
- logrus.Errorf("Error removing temporary auth file %q: %v", authfile, err)
+ logrus.Errorf("Removing temporary auth file %q: %v", authfile, err)
}
}
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 894178bb9..29c234ce9 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -404,7 +404,8 @@ func newerRemoteImageAvailable(ctx context.Context, runtime *libpod.Runtime, img
if err != nil {
return false, err
}
- return img.HasDifferentDigest(ctx, remoteRef)
+ options := &libimage.HasDifferentDigestOptions{AuthFilePath: authfile}
+ return img.HasDifferentDigest(ctx, remoteRef, options)
}
// newerLocalImageAvailable returns true if the container and local image have different digests
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 4127ad2f0..e2c46e481 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -112,12 +112,12 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string)
return nil, errors.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme)
}
if err != nil {
- return nil, errors.Wrapf(err, "failed to create %sClient", _url.Scheme)
+ return nil, errors.Wrapf(err, "unable to connect to Podman. failed to create %sClient", _url.Scheme)
}
ctx = context.WithValue(ctx, clientKey, &connection)
if err := pingNewConnection(ctx); err != nil {
- return nil, errors.Wrap(err, "cannot connect to the Podman socket, please verify the connection to the Linux system, or use `podman machine` to create/start a Linux VM.")
+ return nil, errors.Wrap(err, "unable to connect to Podman socket")
}
return ctx, nil
}
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index 6efbcb57b..abf58aaf9 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -102,7 +102,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
}
defer func() {
if err := terminal.Restore(int(file.Fd()), state); err != nil {
- logrus.Errorf("unable to restore terminal: %q", err)
+ logrus.Errorf("Unable to restore terminal: %q", err)
}
logrus.SetFormatter(&logrus.TextFormatter{})
}()
@@ -166,7 +166,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
_, err := utils.CopyDetachable(socket, stdin, detachKeysInBytes)
if err != nil && err != define.ErrDetach {
- logrus.Error("failed to write input to service: " + err.Error())
+ logrus.Errorf("Failed to write input to service: %v", err)
}
stdinChan <- err
@@ -349,7 +349,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i
resize := func() {
w, h, err := terminal.GetSize(int(file.Fd()))
if err != nil {
- logrus.Warnf("failed to obtain TTY size: %v", err)
+ logrus.Warnf("Failed to obtain TTY size: %v", err)
}
var resizeErr error
@@ -359,7 +359,7 @@ func attachHandleResize(ctx, winCtx context.Context, winChange chan os.Signal, i
resizeErr = ResizeContainerTTY(ctx, id, new(ResizeTTYOptions).WithHeight(h).WithWidth(w))
}
if resizeErr != nil {
- logrus.Infof("failed to resize TTY: %v", resizeErr)
+ logrus.Infof("Failed to resize TTY: %v", resizeErr)
}
}
@@ -443,13 +443,13 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
}
defer func() {
if err := terminal.Restore(int(terminalFile.Fd()), state); err != nil {
- logrus.Errorf("unable to restore terminal: %q", err)
+ logrus.Errorf("Unable to restore terminal: %q", err)
}
logrus.SetFormatter(&logrus.TextFormatter{})
}()
w, h, err := terminal.GetSize(int(terminalFile.Fd()))
if err != nil {
- logrus.Warnf("failed to obtain TTY size: %v", err)
+ logrus.Warnf("Failed to obtain TTY size: %v", err)
}
body.Width = uint16(w)
body.Height = uint16(h)
@@ -502,7 +502,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
logrus.Debugf("Copying STDIN to socket")
_, err := utils.CopyDetachable(socket, options.InputStream, []byte{})
if err != nil {
- logrus.Error("failed to write input to service: " + err.Error())
+ logrus.Errorf("Failed to write input to service: %v", err)
}
if closeWrite, ok := socket.(CloseWriter); ok {
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index 9d5aad23b..8cf4532d0 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -230,6 +230,9 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
params.Add("platform", platform)
}
}
+ if contextDir, err := filepath.EvalSymlinks(options.ContextDirectory); err == nil {
+ options.ContextDirectory = contextDir
+ }
params.Set("pullpolicy", options.PullPolicy.String())
@@ -312,7 +315,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
contextDir, err := filepath.Abs(options.ContextDirectory)
if err != nil {
- logrus.Errorf("cannot find absolute path of %v: %v", options.ContextDirectory, err)
+ logrus.Errorf("Cannot find absolute path of %v: %v", options.ContextDirectory, err)
return nil, err
}
@@ -339,7 +342,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
containerfile, err := filepath.Abs(c)
if err != nil {
- logrus.Errorf("cannot find absolute path of %v: %v", c, err)
+ logrus.Errorf("Cannot find absolute path of %v: %v", c, err)
return nil, err
}
@@ -371,7 +374,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
tarfile, err := nTar(append(excludes, dontexcludes...), tarContent...)
if err != nil {
- logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err)
+ logrus.Errorf("Cannot tar container entries %v error: %v", tarContent, err)
return nil, err
}
defer func() {
@@ -477,7 +480,7 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
for _, src := range sources {
s, err := filepath.Abs(src)
if err != nil {
- logrus.Errorf("cannot stat one of source context: %v", err)
+ logrus.Errorf("Cannot stat one of source context: %v", err)
merr = multierror.Append(merr, err)
return
}
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 801f5ed96..dc6bd91c3 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -65,6 +65,8 @@ type ExportOptions struct {
Compress *bool
// Format of the output
Format *string
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers *bool
}
//go:generate go run ../generator/generator.go PruneOptions
@@ -72,6 +74,8 @@ type ExportOptions struct {
type PruneOptions struct {
// Prune all images
All *bool
+ // Prune images even when they're used by external containers
+ External *bool
// Filters to apply when pruning images
Filters map[string][]string
}
diff --git a/pkg/bindings/images/types_export_options.go b/pkg/bindings/images/types_export_options.go
index 6229e435c..649b6814e 100644
--- a/pkg/bindings/images/types_export_options.go
+++ b/pkg/bindings/images/types_export_options.go
@@ -46,3 +46,18 @@ func (o *ExportOptions) GetFormat() string {
}
return *o.Format
}
+
+// WithOciAcceptUncompressedLayers set field OciAcceptUncompressedLayers to given value
+func (o *ExportOptions) WithOciAcceptUncompressedLayers(value bool) *ExportOptions {
+ o.OciAcceptUncompressedLayers = &value
+ return o
+}
+
+// GetOciAcceptUncompressedLayers returns value of field OciAcceptUncompressedLayers
+func (o *ExportOptions) GetOciAcceptUncompressedLayers() bool {
+ if o.OciAcceptUncompressedLayers == nil {
+ var z bool
+ return z
+ }
+ return *o.OciAcceptUncompressedLayers
+}
diff --git a/pkg/bindings/images/types_prune_options.go b/pkg/bindings/images/types_prune_options.go
index 77bef32e3..c9772045e 100644
--- a/pkg/bindings/images/types_prune_options.go
+++ b/pkg/bindings/images/types_prune_options.go
@@ -32,6 +32,21 @@ func (o *PruneOptions) GetAll() bool {
return *o.All
}
+// WithExternal set field External to given value
+func (o *PruneOptions) WithExternal(value bool) *PruneOptions {
+ o.External = &value
+ return o
+}
+
+// GetExternal returns value of field External
+func (o *PruneOptions) GetExternal() bool {
+ if o.External == nil {
+ var z bool
+ return z
+ }
+ return *o.External
+}
+
// WithFilters set field Filters to given value
func (o *PruneOptions) WithFilters(value map[string][]string) *PruneOptions {
o.Filters = value
diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go
index 9fdf04933..f53e31f9b 100644
--- a/pkg/checkpoint/checkpoint_restore.go
+++ b/pkg/checkpoint/checkpoint_restore.go
@@ -51,7 +51,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
}
defer func() {
if err := os.RemoveAll(dir); err != nil {
- logrus.Errorf("could not recursively remove %s: %q", dir, err)
+ logrus.Errorf("Could not recursively remove %s: %q", dir, err)
}
}()
err = archive.Untar(archiveFile, dir, options)
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index c575212b1..2822b1ad7 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -251,8 +251,9 @@ type ImageListOptions struct {
}
type ImagePruneOptions struct {
- All bool `json:"all" schema:"all"`
- Filter []string `json:"filter" schema:"filter"`
+ All bool `json:"all" schema:"all"`
+ External bool `json:"external" schema:"external"`
+ Filter []string `json:"filter" schema:"filter"`
}
type ImageTagOptions struct{}
@@ -301,10 +302,10 @@ type ImageSaveOptions struct {
// than one image. Additional tags will be interpreted as references
// to images which are added to the archive.
MultiImageArchive bool
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers bool
// Output - write image to the specified path.
Output string
- // Do not save the signature from the source image
- RemoveSignatures bool
// Quiet - suppress output when copying images
Quiet bool
}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index a74725c63..f0c88d77e 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -112,26 +112,28 @@ type PodSpec struct {
PodSpecGen specgen.PodSpecGenerator
}
-// PodCreateOptions provides all possible options for creating a pod and its infra container
+// PodCreateOptions provides all possible options for creating a pod and its infra container.
+// The JSON tags below are made to match the respective field in ContainerCreateOptions for the purpose of mapping.
// swagger:model PodCreateOptions
type PodCreateOptions struct {
- CGroupParent string
- CreateCommand []string
- Hostname string
- Infra bool
- InfraImage string
- InfraName string
- InfraCommand string
- InfraConmonPidFile string
- Labels map[string]string
- Name string
- Net *NetOptions
- Share []string
- Pid string
- Cpus float64
- CpusetCpus string
- Userns specgen.Namespace
- Volume []string
+ CGroupParent string `json:"cgroup_parent,omitempty"`
+ CreateCommand []string `json:"create_command,omitempty"`
+ Devices []string `json:"devices,omitempty"`
+ Hostname string `json:"hostname,omitempty"`
+ Infra bool `json:"infra,omitempty"`
+ InfraImage string `json:"infra_image,omitempty"`
+ InfraName string `json:"container_name,omitempty"`
+ InfraCommand *string `json:"container_command,omitempty"`
+ InfraConmonPidFile string `json:"container_conmon_pidfile,omitempty"`
+ Labels map[string]string `json:"labels,omitempty"`
+ Name string `json:"name,omitempty"`
+ Net *NetOptions `json:"net,omitempty"`
+ Share []string `json:"share,omitempty"`
+ Pid string `json:"pid,omitempty"`
+ Cpus float64 `json:"cpus,omitempty"`
+ CpusetCpus string `json:"cpuset_cpus,omitempty"`
+ Userns specgen.Namespace `json:"-"`
+ Volume []string `json:"volume,omitempty"`
}
// PodLogsOptions describes the options to extract pod logs.
@@ -152,24 +154,24 @@ type ContainerCreateOptions struct {
CapDrop []string
CgroupNS string
CGroupsMode string
- CGroupParent string
+ CGroupParent string `json:"cgroup_parent,omitempty"`
CIDFile string
- ConmonPIDFile string
+ ConmonPIDFile string `json:"container_conmon_pidfile,omitempty"`
CPUPeriod uint64
CPUQuota int64
CPURTPeriod uint64
CPURTRuntime int64
CPUShares uint64
- CPUS float64
- CPUSetCPUs string
+ CPUS float64 `json:"cpus,omitempty"`
+ CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
CPUSetMems string
- Devices []string
+ Devices []string `json:"devices,omitempty"`
DeviceCGroupRule []string
DeviceReadBPs []string
DeviceReadIOPs []string
DeviceWriteBPs []string
DeviceWriteIOPs []string
- Entrypoint *string
+ Entrypoint *string `json:"container_command,omitempty"`
Env []string
EnvHost bool
EnvFile []string
@@ -181,7 +183,7 @@ type ContainerCreateOptions struct {
HealthRetries uint
HealthStartPeriod string
HealthTimeout string
- Hostname string
+ Hostname string `json:"hostname,omitempty"`
HTTPProxy bool
ImageVolume string
Init bool
@@ -198,14 +200,14 @@ type ContainerCreateOptions struct {
MemoryReservation string
MemorySwap string
MemorySwappiness int64
- Name string
+ Name string `json:"container_name,omitempty"`
NoHealthCheck bool
OOMKillDisable bool
OOMScoreAdj int
Arch string
OS string
Variant string
- PID string
+ PID string `json:"pid,omitempty"`
PIDsLimit *int64
Platform string
Pod string
@@ -244,17 +246,17 @@ type ContainerCreateOptions struct {
UIDMap []string
Ulimit []string
User string
- UserNS string
+ UserNS string `json:"-"`
UTS string
Mount []string
- Volume []string
+ Volume []string `json:"volume,omitempty"`
VolumesFrom []string
Workdir string
SeccompPolicy string
PidFile string
IsInfra bool
- Net *NetOptions
+ Net *NetOptions `json:"net,omitempty"`
CgroupConf []string
}
@@ -294,9 +296,10 @@ func ToPodSpecGen(s specgen.PodSpecGenerator, p *PodCreateOptions) (*specgen.Pod
s.Pid = out
s.Hostname = p.Hostname
s.Labels = p.Labels
+ s.Devices = p.Devices
s.NoInfra = !p.Infra
- if len(p.InfraCommand) > 0 {
- s.InfraCommand = strings.Split(p.InfraCommand, " ")
+ if p.InfraCommand != nil && len(*p.InfraCommand) > 0 {
+ s.InfraCommand = strings.Split(*p.InfraCommand, " ")
}
if len(p.InfraConmonPidFile) > 0 {
s.InfraConmonPidFile = p.InfraConmonPidFile
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index dc5f7a0df..8e7e2d411 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -169,6 +169,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
logrus.Debugf("Container %s is already stopped", c.ID())
case options.All && errors.Cause(err) == define.ErrCtrStateInvalid:
logrus.Debugf("Container %s is not running, could not stop", c.ID())
+ // container never created in OCI runtime
+ // docker parity: do nothing just return container id
+ case errors.Cause(err) == define.ErrCtrStateInvalid:
+ logrus.Debugf("Container %s is either not created on runtime or is in a invalid state", c.ID())
default:
return err
}
@@ -825,26 +829,12 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
})
if ctr.AutoRemove() {
if err := ic.removeContainer(ctx, ctr, entities.RmOptions{}); err != nil {
- logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Removing container %s: %v", ctr.ID(), err)
}
}
return reports, errors.Wrapf(err, "unable to start container %s", ctr.ID())
}
-
- if ecode, err := ctr.Wait(ctx); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- // Check events
- event, err := ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
- if err != nil {
- logrus.Errorf("Cannot get exit code: %v", err)
- exitCode = define.ExecErrorCodeNotFound
- } else {
- exitCode = event.ContainerExitCode
- }
- }
- } else {
- exitCode = int(ecode)
- }
+ exitCode = ic.GetContainerExitCode(ctx, ctr)
reports = append(reports, &entities.ContainerStartReport{
Id: ctr.ID(),
RawInput: rawInput,
@@ -874,7 +864,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
reports = append(reports, report)
if ctr.AutoRemove() {
if err := ic.removeContainer(ctx, ctr, entities.RmOptions{}); err != nil {
- logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Removing container %s: %v", ctr.ID(), err)
}
}
continue
@@ -985,34 +975,43 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
report.ExitCode = define.ExitCode(err)
return &report, err
}
-
- if ecode, err := ctr.Wait(ctx); err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
- // Check events
- event, err := ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
- if err != nil {
- logrus.Errorf("Cannot get exit code: %v", err)
- report.ExitCode = define.ExecErrorCodeNotFound
- } else {
- report.ExitCode = event.ContainerExitCode
- }
- }
- } else {
- report.ExitCode = int(ecode)
- }
+ report.ExitCode = ic.GetContainerExitCode(ctx, ctr)
if opts.Rm && !ctr.ShouldRestart(ctx) {
if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr ||
errors.Cause(err) == define.ErrCtrRemoved {
logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID())
} else {
- logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
+ logrus.Errorf("Removing container %s: %v", ctr.ID(), err)
}
}
}
return &report, nil
}
+func (ic *ContainerEngine) GetContainerExitCode(ctx context.Context, ctr *libpod.Container) int {
+ exitCode, err := ctr.Wait(ctx)
+ if err == nil {
+ return int(exitCode)
+ }
+ if errors.Cause(err) != define.ErrNoSuchCtr {
+ logrus.Errorf("Could not retrieve exit code: %v", err)
+ return define.ExecErrorCodeNotFound
+ }
+ // Make 4 attempt with 0.25s backoff between each for 1 second total
+ var event *events.Event
+ for i := 0; i < 4; i++ {
+ event, err = ic.Libpod.GetLastContainerEvent(ctx, ctr.ID(), events.Exited)
+ if err != nil {
+ time.Sleep(250 * time.Millisecond)
+ continue
+ }
+ return int(event.ContainerExitCode)
+ }
+ logrus.Errorf("Could not retrieve exit code from event: %v", err)
+ return define.ExecErrorCodeNotFound
+}
+
func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
if options.StdoutWriter == nil && options.StderrWriter == nil {
return errors.New("no io.Writer set for container logs")
diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go
index 435baa8c8..add82f0fb 100644
--- a/pkg/domain/infra/abi/containers_runlabel.go
+++ b/pkg/domain/infra/abi/containers_runlabel.go
@@ -87,7 +87,7 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string,
ctr, err := ic.Libpod.LookupContainer(name)
if err != nil {
if errors.Cause(err) != define.ErrNoSuchCtr {
- logrus.Debugf("Error occurred searching for container %s: %s", name, err.Error())
+ logrus.Debugf("Error occurred searching for container %s: %v", name, err)
return err
}
} else {
@@ -167,7 +167,7 @@ func generateRunlabelCommand(runlabel string, img *libimage.Image, inputName str
// I would prefer to use os.getenv but it appears PWD is not in the os env list.
d, err := os.Getwd()
if err != nil {
- logrus.Error("unable to determine current working directory")
+ logrus.Error("Unable to determine current working directory")
return ""
}
return d
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index 2d7bc15f5..081a2464b 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -107,7 +107,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
// Generate kube pods and services from pods.
if len(pods) >= 1 {
- pos, svcs, err := getKubePods(pods, options.Service)
+ pos, svcs, err := getKubePods(ctx, pods, options.Service)
if err != nil {
return nil, err
}
@@ -120,7 +120,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
// Generate the kube pods from containers.
if len(ctrs) >= 1 {
- po, err := libpod.GenerateForKube(ctrs)
+ po, err := libpod.GenerateForKube(ctx, ctrs)
if err != nil {
return nil, err
}
@@ -153,12 +153,12 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string,
}
// getKubePods returns kube pod and service YAML files from podman pods.
-func getKubePods(pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) {
+func getKubePods(ctx context.Context, pods []*libpod.Pod, getService bool) ([][]byte, [][]byte, error) {
pos := [][]byte{}
svcs := [][]byte{}
for _, p := range pods {
- po, sp, err := p.GenerateForKube()
+ po, sp, err := p.GenerateForKube(ctx)
if err != nil {
return nil, nil, err
}
@@ -210,9 +210,7 @@ func generateKubeYAML(kubeKind interface{}) ([]byte, error) {
func generateKubeOutput(content [][]byte) ([]byte, error) {
output := make([]byte, 0)
- header := `# Generation of Kubernetes YAML is still under development!
-#
-# Save the output of this file and use kubectl create -f to import
+ header := `# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-%s
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index a88d38a10..c06059205 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -41,13 +41,21 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) {
pruneOptions := &libimage.RemoveImagesOptions{
- Filters: append(opts.Filter, "containers=false", "readonly=false"),
- WithSize: true,
+ RemoveContainerFunc: ir.Libpod.RemoveContainersForImageCallback(ctx),
+ IsExternalContainerFunc: ir.Libpod.IsExternalContainerCallback(ctx),
+ ExternalContainers: opts.External,
+ Filters: append(opts.Filter, "readonly=false"),
+ WithSize: true,
}
if !opts.All {
pruneOptions.Filters = append(pruneOptions.Filters, "dangling=true")
}
+ if opts.External {
+ pruneOptions.Filters = append(pruneOptions.Filters, "containers=external")
+ } else {
+ pruneOptions.Filters = append(pruneOptions.Filters, "containers=false")
+ }
var pruneReports []*reports.PruneReport
@@ -367,7 +375,11 @@ func (ir *ImageEngine) Load(ctx context.Context, options entities.ImageLoadOptio
func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, options entities.ImageSaveOptions) error {
saveOptions := &libimage.SaveOptions{}
saveOptions.DirForceCompress = options.Compress
- saveOptions.RemoveSignatures = options.RemoveSignatures
+ saveOptions.OciAcceptUncompressedLayers = options.OciAcceptUncompressedLayers
+
+ // Force signature removal to preserve backwards compat.
+ // See https://github.com/containers/podman/pull/11669#issuecomment-925250264
+ saveOptions.RemoveSignatures = true
if !options.Quiet {
saveOptions.Writer = os.Stderr
@@ -572,7 +584,7 @@ func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entitie
}
defer func() {
if err = rawSource.Close(); err != nil {
- logrus.Errorf("unable to close %s image source %q", srcRef.DockerReference().Name(), err)
+ logrus.Errorf("Unable to close %s image source %q", srcRef.DockerReference().Name(), err)
}
}()
topManifestBlob, manifestType, err := rawSource.GetManifest(ctx, nil)
diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go
index 1dd0686ac..d1bd5e2e4 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -146,7 +146,7 @@ func (ir *ImageEngine) remoteManifestInspect(ctx context.Context, name string) (
switch manType {
case manifest.DockerV2Schema2MediaType:
- logrus.Warnf("Warning! The manifest type %s is not a manifest list but a single image.", manType)
+ logrus.Warnf("The manifest type %s is not a manifest list but a single image.", manType)
schema2Manifest, err := manifest.Schema2FromManifest(result)
if err != nil {
return nil, errors.Wrapf(err, "error parsing manifest blob %q as a %q", string(result), manType)
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 87506f70c..cf72a6253 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -113,7 +113,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
report.Volumes = append(report.Volumes, r.Volumes...)
validKinds++
default:
- logrus.Infof("kube kind %s not supported", kind)
+ logrus.Infof("Kube kind %s not supported", kind)
continue
}
}
@@ -319,8 +319,8 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
-
specgenOpts := kube.CtrSpecGenOptions{
+ Annotations: annotations,
Container: initCtr,
Image: pulledImage,
Volumes: volumes,
@@ -435,6 +435,7 @@ func (ic *ContainerEngine) getImageAndLabelInfo(ctx context.Context, cwd string,
buildOpts.Isolation = buildahDefine.IsolationChroot
buildOpts.CommonBuildOpts = commonOpts
buildOpts.Output = container.Image
+ buildOpts.ContextDirectory = filepath.Dir(buildFile)
if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil {
return nil, nil, err
}
@@ -662,21 +663,21 @@ func getBuildFile(imageName string, cwd string) (string, error) {
containerfilePath := filepath.Join(cwd, buildDirName, "Containerfile")
dockerfilePath := filepath.Join(cwd, buildDirName, "Dockerfile")
- _, err := os.Stat(filepath.Join(containerfilePath))
+ _, err := os.Stat(containerfilePath)
if err == nil {
- logrus.Debugf("building %s with %s", imageName, containerfilePath)
+ logrus.Debugf("Building %s with %s", imageName, containerfilePath)
return containerfilePath, nil
}
// If the error is not because the file does not exist, take
// a mulligan and try Dockerfile. If that also fails, return that
// error
if err != nil && !os.IsNotExist(err) {
- logrus.Errorf("%v: unable to check for %s", err, containerfilePath)
+ logrus.Error(err.Error())
}
_, err = os.Stat(filepath.Join(dockerfilePath))
if err == nil {
- logrus.Debugf("building %s with %s", imageName, dockerfilePath)
+ logrus.Debugf("Building %s with %s", imageName, dockerfilePath)
return dockerfilePath, nil
}
// Strike two
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 2bf8eaae3..34c230e75 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -21,7 +21,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
// set defaults from config for the case they are not set by an upper layer
// (-> i.e. tests that talk directly to the api)
- cfg, err := ic.Libpod.GetConfig()
+ cfg, err := ic.Libpod.GetConfigNoCopy()
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
index a9bd2d5fb..3b129f5ea 100644
--- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go
+++ b/pkg/domain/infra/abi/terminal/sigproxy_linux.go
@@ -42,7 +42,7 @@ func ProxySignals(ctr *libpod.Container) {
if errors.Cause(err) == define.ErrCtrStateInvalid {
logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID())
} else {
- logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err)
+ logrus.Errorf("forwarding signal %d to container %s: %v", s, ctr.ID(), err)
}
// If the container dies, and we find out here,
// we need to forward that one signal to
@@ -51,7 +51,7 @@ func ProxySignals(ctr *libpod.Container) {
// play out.
signal.StopCatch(sigBuffer)
if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil {
- logrus.Errorf("failed to kill pid %d", syscall.Getpid())
+ logrus.Errorf("Failed to kill pid %d", syscall.Getpid())
}
return
}
diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go
index 09c0f802d..ba047bf33 100644
--- a/pkg/domain/infra/abi/terminal/terminal_linux.go
+++ b/pkg/domain/infra/abi/terminal/terminal_linux.go
@@ -29,7 +29,7 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo
defer cancel()
defer func() {
if err := restoreTerminal(oldTermState); err != nil {
- logrus.Errorf("unable to restore terminal: %q", err)
+ logrus.Errorf("Unable to restore terminal: %q", err)
}
}()
}
@@ -53,7 +53,7 @@ func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr,
}
defer func() {
if err := restoreTerminal(oldTermState); err != nil {
- logrus.Errorf("unable to restore terminal: %q", err)
+ logrus.Errorf("Unable to restore terminal: %q", err)
}
}()
defer cancel()
diff --git a/pkg/domain/infra/abi/trust.go b/pkg/domain/infra/abi/trust.go
index d3aff62ba..af7814163 100644
--- a/pkg/domain/infra/abi/trust.go
+++ b/pkg/domain/infra/abi/trust.go
@@ -165,7 +165,7 @@ var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "sig
func trustTypeDescription(trustType string) string {
trustDescription, exist := typeDescription[trustType]
if !exist {
- logrus.Warnf("invalid trust type %s", trustType)
+ logrus.Warnf("Invalid trust type %s", trustType)
}
return trustDescription
}
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index 5cbee2e76..7ec6135ee 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -369,7 +369,7 @@ func StartWatcher(rt *libpod.Runtime) {
logrus.Debugf("waiting for SIGHUP to reload configuration")
<-ch
if err := rt.Reload(); err != nil {
- logrus.Errorf("unable to reload configuration: %v", err)
+ logrus.Errorf("Unable to reload configuration: %v", err)
continue
}
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 81ddce42f..9fe2d163c 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -561,7 +561,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
errorhandling.Contains(err, define.ErrCtrRemoved) {
logrus.Debugf("Container %s does not exist: %v", id, err)
} else {
- logrus.Errorf("Error removing container %s: %v", id, err)
+ logrus.Errorf("Removing container %s: %v", id, err)
}
}
}
@@ -646,7 +646,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
errorhandling.Contains(err, types.ErrLayerUnknown) {
logrus.Debugf("Container %s does not exist: %v", ctr.ID, err)
} else {
- logrus.Errorf("Error removing container %s: %v", ctr.ID, err)
+ logrus.Errorf("Removing container %s: %v", ctr.ID, err)
}
}
}
@@ -731,7 +731,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
errorhandling.Contains(err, types.ErrLayerUnknown) {
logrus.Debugf("Container %s does not exist: %v", con.ID, err)
} else {
- logrus.Errorf("Error removing container %s: %v", con.ID, err)
+ logrus.Errorf("Removing container %s: %v", con.ID, err)
}
}
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index db4e14aba..d41a20348 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -95,7 +95,7 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption
f := strings.Split(filter, "=")
filters[f[0]] = f[1:]
}
- options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters)
+ options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters).WithExternal(opts.External)
reports, err := images.Prune(ir.ClientCtx, options)
if err != nil {
return nil, err
@@ -165,6 +165,9 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string
if t, ok := ref.(reference.Tagged); ok {
tag = t.Tag()
}
+ if t, ok := ref.(reference.Digested); ok {
+ tag += "@" + t.Digest().String()
+ }
if r, ok := ref.(reference.Named); ok {
repo = r.Name()
}
@@ -253,6 +256,7 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string,
err error
)
options := new(images.ExportOptions).WithFormat(opts.Format).WithCompress(opts.Compress)
+ options = options.WithOciAcceptUncompressedLayers(opts.OciAcceptUncompressedLayers)
switch opts.Format {
case "oci-dir", "docker-dir":
diff --git a/pkg/env/env.go b/pkg/env/env.go
index 0d55e5560..ecd2d62a5 100644
--- a/pkg/env/env.go
+++ b/pkg/env/env.go
@@ -17,8 +17,9 @@ const whiteSpaces = " \t"
// DefaultEnvVariables returns a default environment, with $PATH and $TERM set.
func DefaultEnvVariables() map[string]string {
return map[string]string{
- "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "TERM": "xterm",
+ "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM": "xterm",
+ "container": "podman",
}
}
diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go
index 6adbc9f34..44a0c3efd 100644
--- a/pkg/errorhandling/errorhandling.go
+++ b/pkg/errorhandling/errorhandling.go
@@ -63,7 +63,7 @@ func StringsToErrors(strErrs []string) []error {
// a defer.
func SyncQuiet(f *os.File) {
if err := f.Sync(); err != nil {
- logrus.Errorf("unable to sync file %s: %q", f.Name(), err)
+ logrus.Errorf("Unable to sync file %s: %q", f.Name(), err)
}
}
@@ -71,7 +71,7 @@ func SyncQuiet(f *os.File) {
// a defer.
func CloseQuiet(f *os.File) {
if err := f.Close(); err != nil {
- logrus.Errorf("unable to close file %s: %q", f.Name(), err)
+ logrus.Errorf("Unable to close file %s: %q", f.Name(), err)
}
}
diff --git a/pkg/hooks/exec/exec.go b/pkg/hooks/exec/exec.go
index f6b6636ad..2b7bc5f31 100644
--- a/pkg/hooks/exec/exec.go
+++ b/pkg/hooks/exec/exec.go
@@ -56,7 +56,7 @@ func Run(ctx context.Context, hook *rspec.Hook, state []byte, stdout io.Writer,
return err, err
case <-ctx.Done():
if err := cmd.Process.Kill(); err != nil {
- logrus.Errorf("failed to kill pid %v", cmd.Process)
+ logrus.Errorf("Failed to kill pid %v", cmd.Process)
}
timer := time.NewTimer(postKillTimeout)
defer timer.Stop()
diff --git a/pkg/hooks/exec/runtimeconfigfilter.go b/pkg/hooks/exec/runtimeconfigfilter.go
index 10b8fedc2..3ab3073b2 100644
--- a/pkg/hooks/exec/runtimeconfigfilter.go
+++ b/pkg/hooks/exec/runtimeconfigfilter.go
@@ -61,7 +61,7 @@ func RuntimeConfigFilter(ctx context.Context, hooks []spec.Hook, config *spec.Sp
if err == nil {
logrus.Debugf("precreate hook %d made configuration changes:\n%s", i, diff)
} else {
- logrus.Warnf("precreate hook %d made configuration changes, but we could not compute a diff: %v", i, err)
+ logrus.Warnf("Precreate hook %d made configuration changes, but we could not compute a diff: %v", i, err)
}
}
diff --git a/pkg/hooks/monitor.go b/pkg/hooks/monitor.go
index 6fa94cd17..ece6e52d1 100644
--- a/pkg/hooks/monitor.go
+++ b/pkg/hooks/monitor.go
@@ -36,7 +36,7 @@ func (m *Manager) Monitor(ctx context.Context, sync chan<- error) {
for _, dir := range m.directories {
err = watcher.Add(dir)
if err != nil {
- logrus.Errorf("failed to watch %q for hooks", dir)
+ logrus.Errorf("Failed to watch %q for hooks", dir)
sync <- err
return
}
@@ -52,7 +52,7 @@ func (m *Manager) Monitor(ctx context.Context, sync chan<- error) {
for _, dir := range m.directories {
err = ReadDir(dir, m.extensionStages, m.hooks)
if err != nil {
- logrus.Errorf("failed loading hooks for %s: %v", event.Name, err)
+ logrus.Errorf("Failed loading hooks for %s: %v", event.Name, err)
}
}
case <-ctx.Done():
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index 8db2335aa..3ff5c7fe7 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -58,6 +58,9 @@ type ListResponse struct {
LastUp time.Time
Running bool
VMType string
+ CPUs uint64
+ Memory uint64
+ DiskSize uint64
}
type SSHOptions struct {
diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go
index cfcadeb02..99197ac0e 100644
--- a/pkg/machine/fcos.go
+++ b/pkg/machine/fcos.go
@@ -139,6 +139,8 @@ func getFCOSDownload(imageStream string) (*fcosDownloadInfo, error) {
)
switch imageStream {
case "testing", "":
+ streamType = fedoracoreos.StreamTesting
+ case "next":
streamType = fedoracoreos.StreamNext
case "stable":
streamType = fedoracoreos.StreamStable
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 89b556b14..e211f5ea6 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
+ "net/url"
)
/*
@@ -80,6 +81,7 @@ func NewIgnitionFile(ign DynamicIgnition) error {
// so a listening host knows it can being interacting with it
ready := `[Unit]
Requires=dev-virtio\\x2dports-%s.device
+After=remove-moby.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
@@ -89,6 +91,23 @@ ExecStart=/bin/sh -c '/usr/bin/echo Ready >/dev/%s'
[Install]
RequiredBy=multi-user.target
`
+ deMoby := `[Unit]
+Description=Remove moby-engine
+# Run once for the machine
+After=systemd-machine-id-commit.service
+Before=zincati.service
+ConditionPathExists=!/var/lib/%N.stamp
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/bin/rpm-ostree override remove moby-engine
+ExecStart=/usr/bin/rpm-ostree ex apply-live --allow-replacement
+ExecStartPost=/bin/touch /var/lib/%N.stamp
+
+[Install]
+WantedBy=multi-user.target
+ `
_ = ready
ignSystemd := Systemd{
Units: []Unit{
@@ -101,6 +120,21 @@ RequiredBy=multi-user.target
Name: "ready.service",
Contents: strToPtr(fmt.Sprintf(ready, "vport1p1", "vport1p1")),
},
+ {
+ Enabled: boolToPtr(false),
+ Name: "docker.service",
+ Mask: boolToPtr(true),
+ },
+ {
+ Enabled: boolToPtr(false),
+ Name: "docker.socket",
+ Mask: boolToPtr(true),
+ },
+ {
+ Enabled: boolToPtr(true),
+ Name: "remove-moby.service",
+ Contents: &deMoby,
+ },
}}
ignConfig := Config{
Ignition: ignVersion,
@@ -161,6 +195,22 @@ func getFiles(usrName string) []File {
var (
files []File
)
+
+ lingerExample := `[Unit]
+Description=A systemd user unit demo
+After=network-online.target
+Wants=network-online.target podman.socket
+[Service]
+ExecStart=/usr/bin/sleep infinity
+`
+ containers := `[containers]
+netns="bridge"
+rootless_networking="cni"
+`
+ rootContainers := `[engine]
+machine_enabled=true
+`
+
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
Node: Node{
@@ -171,7 +221,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5BUnit%5D%0ADescription%3DA%20systemd%20user%20unit%20demo%0AAfter%3Dnetwork-online.target%0AWants%3Dnetwork-online.target%20podman.socket%0A%5BService%5D%0AExecStart%3D%2Fusr%2Fbin%2Fsleep%20infinity%0A"),
+ Source: encodeDataURLPtr(lingerExample),
},
Mode: intToPtr(0744),
},
@@ -188,7 +238,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"),
+ Source: encodeDataURLPtr(containers),
},
Mode: intToPtr(0744),
},
@@ -213,7 +263,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"),
+ Source: encodeDataURLPtr(rootContainers),
},
Mode: intToPtr(0644),
},
@@ -233,7 +283,22 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,unqualified-search-registries%3D%5B%22docker.io%22%5D"),
+ Source: encodeDataURLPtr("unqualified-search-registries=[\"docker.io\"]\n"),
+ },
+ Mode: intToPtr(0644),
+ },
+ })
+
+ files = append(files, File{
+ Node: Node{
+ Path: "/etc/tmpfiles.d/podman-docker.conf",
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ // Create a symlink from the docker socket to the podman socket.
+ // Taken from https://github.com/containers/podman/blob/main/contrib/systemd/system/podman-docker.conf
+ Contents: Resource{
+ Source: encodeDataURLPtr("L+ /run/docker.sock - - - - /run/podman/podman.sock\n"),
},
Mode: intToPtr(0644),
},
@@ -253,5 +318,20 @@ func getLinks(usrName string) []Link {
Hard: boolToPtr(false),
Target: "/home/" + usrName + "/.config/systemd/user/linger-example.service",
},
+ }, {
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/usr/local/bin/docker",
+ Overwrite: boolToPtr(true),
+ User: getNodeUsr("root"),
+ },
+ LinkEmbedded1: LinkEmbedded1{
+ Hard: boolToPtr(false),
+ Target: "/usr/bin/podman",
+ },
}}
}
+
+func encodeDataURLPtr(contents string) *string {
+ return strToPtr(fmt.Sprintf("data:,%s", url.PathEscape(contents)))
+}
diff --git a/pkg/machine/qemu/config.go b/pkg/machine/qemu/config.go
index 3d0fa4094..9f5f45b58 100644
--- a/pkg/machine/qemu/config.go
+++ b/pkg/machine/qemu/config.go
@@ -17,6 +17,8 @@ type MachineVM struct {
ImagePath string
// Memory in megabytes assigned to the vm
Memory uint64
+ // Disk size in gigabytes assigned to the vm
+ DiskSize uint64
// Name of the vm
Name string
// SSH port for user networking
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index d5f538594..c4e6aa611 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -64,6 +64,7 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
vm.CPUs = opts.CPUS
vm.Memory = opts.Memory
+ vm.DiskSize = opts.DiskSize
// Look up the executable
execPath, err := exec.LookPath(QemuCommand)
@@ -140,7 +141,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
v.IdentityPath = filepath.Join(sshDir, v.Name)
switch opts.ImagePath {
- case "testing", "stable", "":
+ case "testing", "next", "stable", "":
// Get image as usual
dd, err := machine.NewFcosDownloader(vmtype, v.Name, opts.ImagePath)
if err != nil {
@@ -366,7 +367,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
return err
}
if _, err := os.Stat(pidFile); os.IsNotExist(err) {
- logrus.Infof("pid file %s does not exist", pidFile)
+ logrus.Info(err)
return nil
}
pidString, err := ioutil.ReadFile(pidFile)
@@ -391,7 +392,12 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
logrus.Warn(err)
}
// Remove socket
- return os.Remove(qemuSocketFile)
+ if err := os.Remove(qemuSocketFile); err != nil {
+ return err
+ }
+
+ fmt.Printf("Successfully stopped machine: %s", name)
+ return nil
}
// NewQMPMonitor creates the monitor subsection of our vm
@@ -574,6 +580,9 @@ func GetVMInfos() ([]*machine.ListResponse, error) {
listEntry.Name = vm.Name
listEntry.VMType = "qemu"
+ listEntry.CPUs = vm.CPUs
+ listEntry.Memory = vm.Memory
+ listEntry.DiskSize = vm.DiskSize
fi, err := os.Stat(fullPath)
if err != nil {
return err
diff --git a/pkg/netns/netns_linux.go b/pkg/netns/netns_linux.go
index c13ae2f4d..3e6e668b5 100644
--- a/pkg/netns/netns_linux.go
+++ b/pkg/netns/netns_linux.go
@@ -133,19 +133,19 @@ func NewNSWithName(name string) (ns.NetNS, error) {
var origNS ns.NetNS
origNS, err = ns.GetNS(threadNsPath)
if err != nil {
- logrus.Warnf("cannot open current network namespace %s: %q", threadNsPath, err)
+ logrus.Warnf("Cannot open current network namespace %s: %q", threadNsPath, err)
return
}
defer func() {
if err := origNS.Close(); err != nil {
- logrus.Errorf("unable to close namespace: %q", err)
+ logrus.Errorf("Unable to close namespace: %q", err)
}
}()
// create a new netns on the current thread
err = unix.Unshare(unix.CLONE_NEWNET)
if err != nil {
- logrus.Warnf("cannot create a new network namespace: %q", err)
+ logrus.Warnf("Cannot create a new network namespace: %q", err)
return
}
@@ -157,7 +157,7 @@ func NewNSWithName(name string) (ns.NetNS, error) {
// the network namespace owned by root on the host.
return
}
- logrus.Warnf("unable to reset namespace: %q", err)
+ logrus.Warnf("Unable to reset namespace: %q", err)
}
}()
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 54079baa1..0f154c524 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -139,11 +139,11 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
}
startedTime, err = c.StartedTime()
if err != nil {
- logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
+ logrus.Errorf("Getting started time for %q: %v", c.ID(), err)
}
exitedTime, err = c.FinishedTime()
if err != nil {
- logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
+ logrus.Errorf("Getting exited time for %q: %v", c.ID(), err)
}
pid, err = c.PID()
@@ -170,12 +170,12 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
rootFsSize, err := c.RootFsSize()
if err != nil {
- logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
+ logrus.Errorf("Getting root fs size for %q: %v", c.ID(), err)
}
rwSize, err := c.RWSize()
if err != nil {
- logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
+ logrus.Errorf("Getting rw size for %q: %v", c.ID(), err)
}
size.RootFsSize = rootFsSize
@@ -241,6 +241,13 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
UTS: uts,
}
}
+
+ if hc, err := ctr.HealthCheckStatus(); err == nil {
+ ps.Status = hc
+ } else {
+ logrus.Debug(err)
+ }
+
return ps, nil
}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 4d8443fcb..6ce4b1e29 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -212,6 +212,7 @@ can_use_shortcut ()
continue;
if (strcmp (argv[argc], "mount") == 0
+ || strcmp (argv[argc], "machine") == 0
|| strcmp (argv[argc], "search") == 0
|| (strcmp (argv[argc], "system") == 0 && argv[argc+1] && strcmp (argv[argc+1], "service") != 0))
{
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index c046ecde7..7f9228666 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -61,20 +61,20 @@ func IsRootless() bool {
if rootlessUIDInit != 0 {
// This happens if we joined the user+mount namespace as part of
if err := os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done"); err != nil {
- logrus.Errorf("failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done")
+ logrus.Errorf("Failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done")
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit)); err != nil {
- logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit)
+ logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit)
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit)); err != nil {
- logrus.Errorf("failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit)
+ logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit)
}
}
isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != ""
if !isRootless {
hasCapSysAdmin, err := unshare.HasCapSysAdmin()
if err != nil {
- logrus.Warnf("failed to read CAP_SYS_ADMIN presence for the current process")
+ logrus.Warnf("Failed to read CAP_SYS_ADMIN presence for the current process")
}
if err == nil && !hasCapSysAdmin {
isRootless = true
@@ -284,12 +284,12 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
toWrite = []byte("1")
}
if _, err := w.Write(toWrite); err != nil {
- logrus.Errorf("failed to write byte 0: %q", err)
+ logrus.Errorf("Failed to write byte 0: %q", err)
}
if retErr != nil && pid > 0 {
if err := unix.Kill(pid, unix.SIGKILL); err != nil {
if err != unix.ESRCH {
- logrus.Errorf("failed to cleanup process %d: %v", pid, err)
+ logrus.Errorf("Failed to cleanup process %d: %v", pid, err)
}
}
C.reexec_in_user_namespace_wait(C.int(pid), 0)
@@ -325,7 +325,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
uidsMapped = err == nil
}
if !uidsMapped {
- logrus.Warnf("using rootless single mapping into the namespace. This might break some images. Check /etc/subuid and /etc/subgid for adding sub*ids")
+ logrus.Warnf("Using rootless single mapping into the namespace. This might break some images. Check /etc/subuid and /etc/subgid for adding sub*ids")
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
if err != nil {
@@ -416,7 +416,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
if err := unix.Kill(int(pidC), s.(unix.Signal)); err != nil {
if err != unix.ESRCH {
- logrus.Errorf("failed to propagate signal to child process %d: %v", int(pidC), err)
+ logrus.Errorf("Failed to propagate signal to child process %d: %v", int(pidC), err)
}
}
}
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go
index 6c7b8e6d7..37fb7ce79 100644
--- a/pkg/rootlessport/rootlessport_linux.go
+++ b/pkg/rootlessport/rootlessport_linux.go
@@ -125,17 +125,17 @@ func parent() error {
quit := make(chan struct{})
errCh := make(chan error)
// start the parent driver. initComplete will be closed when the child connected to the parent.
- logrus.Infof("starting parent driver")
+ logrus.Infof("Starting parent driver")
go func() {
driverErr := driver.RunParentDriver(initComplete, quit, nil)
if driverErr != nil {
- logrus.WithError(driverErr).Warn("parent driver exited")
+ logrus.WithError(driverErr).Warn("Parent driver exited")
}
errCh <- driverErr
close(errCh)
}()
opaque := driver.OpaqueForChild()
- logrus.Infof("opaque=%+v", opaque)
+ logrus.Infof("Opaque=%+v", opaque)
opaqueJSON, err := json.Marshal(opaque)
if err != nil {
return err
@@ -146,9 +146,9 @@ func parent() error {
}
defer func() {
// stop the child
- logrus.Info("stopping child driver")
+ logrus.Info("Stopping child driver")
if err := childQuitW.Close(); err != nil {
- logrus.WithError(err).Warn("unable to close childQuitW")
+ logrus.WithError(err).Warn("Unable to close childQuitW")
}
}()
@@ -164,7 +164,7 @@ func parent() error {
return err
}
if err := childNS.Do(func(_ ns.NetNS) error {
- logrus.Infof("starting child driver in child netns (%q %v)", cmd.Path, cmd.Args)
+ logrus.Infof("Starting child driver in child netns (%q %v)", cmd.Path, cmd.Args)
return cmd.Start()
}); err != nil {
return err
@@ -179,11 +179,11 @@ func parent() error {
defer func() {
if err := unix.Kill(cmd.Process.Pid, unix.SIGTERM); err != nil {
- logrus.WithError(err).Warn("kill child process")
+ logrus.WithError(err).Warn("Kill child process")
}
}()
- logrus.Info("waiting for initComplete")
+ logrus.Info("Waiting for initComplete")
// wait for the child to connect to the parent
outer:
for {
@@ -203,15 +203,15 @@ outer:
}
defer func() {
- logrus.Info("stopping parent driver")
+ logrus.Info("Stopping parent driver")
quit <- struct{}{}
if err := <-errCh; err != nil {
- logrus.WithError(err).Warn("parent driver returned error on exit")
+ logrus.WithError(err).Warn("Parent driver returned error on exit")
}
}()
// let parent expose ports
- logrus.Infof("exposing ports %v", cfg.Mappings)
+ logrus.Infof("Exposing ports %v", cfg.Mappings)
if err := exposePorts(driver, cfg.Mappings, cfg.ChildIP); err != nil {
return err
}
@@ -235,13 +235,13 @@ outer:
// remove the socket file on exit
defer os.Remove(socketfile)
if err != nil {
- logrus.Warnf("failed to close the socketDir fd: %v", err)
+ logrus.Warnf("Failed to close the socketDir fd: %v", err)
}
defer socket.Close()
go serve(socket, driver)
}
- logrus.Info("ready")
+ logrus.Info("Ready")
// https://github.com/containers/podman/issues/11248
// Copy /dev/null to stdout and stderr to prevent SIGPIPE errors
@@ -259,7 +259,7 @@ outer:
}
// wait for ExitFD to be closed
- logrus.Info("waiting for exitfd to be closed")
+ logrus.Info("Waiting for exitfd to be closed")
if _, err := ioutil.ReadAll(exitR); err != nil {
return err
}
@@ -353,10 +353,10 @@ func child() error {
errCh <- dErr
}()
defer func() {
- logrus.Info("stopping child driver")
+ logrus.Info("Stopping child driver")
quit <- struct{}{}
if err := <-errCh; err != nil {
- logrus.WithError(err).Warn("child driver returned error on exit")
+ logrus.WithError(err).Warn("Child driver returned error on exit")
}
}()
diff --git a/pkg/servicereaper/service.go b/pkg/servicereaper/service.go
index e9c4fe908..e105148f0 100644
--- a/pkg/servicereaper/service.go
+++ b/pkg/servicereaper/service.go
@@ -46,7 +46,7 @@ func reaper(sigc chan os.Signal) {
if err != nil {
// do not log error for ECHILD
if err != syscall.ECHILD {
- logrus.Warnf("wait for pid %d failed: %v ", pid, err)
+ logrus.Warnf("Wait for pid %d failed: %v ", pid, err)
}
delete(s.pidMap, pid)
continue
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index 6b9e9c4bf..2d1e2b288 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -132,7 +132,6 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
}
return nil
}
-
return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
}
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index ae26807a9..71b882510 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -54,7 +54,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
}
- rtc, err := r.GetConfig()
+ rtc, err := r.GetConfigNoCopy()
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 91230338e..6100e7a5b 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -23,31 +23,34 @@ import (
// Returns the created, container and any warnings resulting from creating the
// container, or an error.
func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) {
- rtc, err := rt.GetConfig()
+ rtc, err := rt.GetConfigNoCopy()
if err != nil {
return nil, nil, nil, err
}
// If joining a pod, retrieve the pod for use, and its infra container
var pod *libpod.Pod
- var cont *libpod.Container
- var config *libpod.ContainerConfig
+ var infraConfig *libpod.ContainerConfig
if s.Pod != "" {
pod, err = rt.LookupPod(s.Pod)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
}
if pod.HasInfraContainer() {
- cont, err = pod.InfraContainer()
+ infra, err := pod.InfraContainer()
if err != nil {
return nil, nil, nil, err
}
- config = cont.Config()
+ infraConfig = infra.Config()
}
}
- if config != nil && (len(config.NamedVolumes) > 0 || len(config.UserVolumes) > 0 || len(config.ImageVolumes) > 0 || len(config.OverlayVolumes) > 0) {
- s.VolumesFrom = append(s.VolumesFrom, config.ID)
+ if infraConfig != nil && (len(infraConfig.NamedVolumes) > 0 || len(infraConfig.UserVolumes) > 0 || len(infraConfig.ImageVolumes) > 0 || len(infraConfig.OverlayVolumes) > 0) {
+ s.VolumesFrom = append(s.VolumesFrom, infraConfig.ID)
+ }
+
+ if infraConfig != nil && len(infraConfig.Spec.Linux.Devices) > 0 {
+ s.DevicesFrom = append(s.DevicesFrom, infraConfig.ID)
}
// Set defaults for unset namespaces
if s.PidNS.IsDefault() {
@@ -166,6 +169,16 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
logrus.Debugf("setting container name %s", s.Name)
options = append(options, libpod.WithName(s.Name))
}
+ if len(s.DevicesFrom) > 0 {
+ for _, dev := range s.DevicesFrom {
+ ctr, err := rt.GetContainer(dev)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ devices := ctr.DeviceHostSrc()
+ s.Devices = append(s.Devices, devices...)
+ }
+ }
if len(s.Devices) > 0 {
opts = extractCDIDevices(s)
options = append(options, opts...)
@@ -174,6 +187,9 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
if err != nil {
return nil, nil, nil, err
}
+ if len(s.HostDeviceList) > 0 {
+ options = append(options, libpod.WithHostDevice(s.HostDeviceList))
+ }
return runtimeSpec, s, options, err
}
func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) {
@@ -482,6 +498,7 @@ func CreateExitCommandArgs(storageConfig types.StoreOptions, config *config.Conf
"--log-level", logrus.GetLevel().String(),
"--cgroup-manager", config.Engine.CgroupManager,
"--tmpdir", config.Engine.TmpDir,
+ "--cni-config-dir", config.Network.NetworkConfigDir,
}
if config.Engine.OCIRuntime != "" {
command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...)
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index c01d7a1f0..9389b1a20 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/parse"
"github.com/containers/common/pkg/secrets"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
ann "github.com/containers/podman/v3/pkg/annotations"
"github.com/containers/podman/v3/pkg/domain/entities"
@@ -86,6 +87,8 @@ func ToPodOpt(ctx context.Context, podName string, p entities.PodCreateOptions,
}
type CtrSpecGenOptions struct {
+ // Annotations from the Pod
+ Annotations map[string]string
// Container as read from the pod yaml
Container v1.Container
// Image available to use (pulled or found local)
@@ -157,7 +160,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
return nil, errors.Wrap(err, "Failed to set CPU quota")
}
if milliCPU > 0 {
- period, quota := util.CoresToPeriodAndQuota(float64(milliCPU) / 1000)
+ period, quota := util.CoresToPeriodAndQuota(float64(milliCPU))
s.ResourceLimits.CPU = &spec.LinuxCPU{
Quota: &quota,
Period: &period,
@@ -289,6 +292,14 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
volume.MountPath = dest
switch volumeSource.Type {
case KubeVolumeTypeBindMount:
+ // If the container has bind mounts, we need to check if
+ // a selinux mount option exists for it
+ for k, v := range opts.Annotations {
+ // Make sure the z/Z option is not already there (from editing the YAML)
+ if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !util.StringInSlice("z", options) && !util.StringInSlice("Z", options) {
+ options = append(options, v)
+ }
+ }
mount := spec.Mount{
Destination: volume.MountPath,
Source: volumeSource.Source,
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 80c7f112f..beccd9fc2 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -62,7 +62,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error {
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
- logrus.Warnf("failed to return RLIMIT_NOFILE ulimit %q", err)
+ logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
}
if rlimit.Cur < current {
current = rlimit.Cur
@@ -79,7 +79,7 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error {
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil {
- logrus.Warnf("failed to return RLIMIT_NPROC ulimit %q", err)
+ logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)
}
if rlimit.Cur < current {
current = rlimit.Cur
@@ -301,8 +301,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
g.AddProcessEnv("container", "podman")
g.Config.Linux.Resources = s.ResourceLimits
-
// Devices
+
if s.Privileged {
// If privileged, we need to add all the host devices to the
// spec. We do not add the user provided ones because we are
@@ -313,17 +313,18 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
} else {
// add default devices from containers.conf
for _, device := range rtc.Containers.Devices {
- if err := DevicesFromPath(&g, device); err != nil {
+ if err = DevicesFromPath(&g, device); err != nil {
return nil, err
}
}
// add default devices specified by caller
for _, device := range s.Devices {
- if err := DevicesFromPath(&g, device.Path); err != nil {
+ if err = DevicesFromPath(&g, device.Path); err != nil {
return nil, err
}
}
}
+ s.HostDeviceList = s.Devices
for _, dev := range s.DeviceCGroupRule {
g.AddLinuxResourcesDevice(true, dev.Type, dev.Major, dev.Minor, dev.Access)
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index a12cc09e2..a11debdb5 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -139,7 +139,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
if len(privCapsRequired) == 0 {
caplist = capsRequired
} else {
- logrus.Errorf("capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ","))
+ logrus.Errorf("Capabilities requested by user or image are not allowed by default: %q", strings.Join(privCapsRequired, ","))
}
}
}
diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go
index 50efe7fa3..b0d84825e 100644
--- a/pkg/specgen/generate/validate.go
+++ b/pkg/specgen/generate/validate.go
@@ -72,10 +72,9 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error
// Pids checks
if s.ResourceLimits.Pids != nil {
- pids := s.ResourceLimits.Pids
// TODO: Should this be 0, or checking that ResourceLimits.Pids
// is set at all?
- if pids.Limit > 0 && !sysInfo.PidsLimit {
+ if s.ResourceLimits.Pids.Limit >= 0 && !sysInfo.PidsLimit {
warnings = append(warnings, "Your kernel does not support pids limit capabilities or the cgroup is not mounted. PIDs limit discarded.")
s.ResourceLimits.Pids = nil
}
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 5f72fc47d..83fa9426c 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -88,6 +88,8 @@ type PodBasicConfig struct {
// Image volumes bind-mount a container-image mount into the pod's infra container.
// Optional.
ImageVolumes []*ImageVolume `json:"image_volumes,omitempty"`
+ // Devices contains user specified Devices to be added to the Pod
+ Devices []string `json:"pod_devices,omitempty"`
}
// PodNetworkConfig contains networking configuration for a pod.
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index e0609c5bc..7aa27487a 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -254,6 +254,10 @@ type ContainerStorageConfig struct {
// DeviceCGroupRule are device cgroup rules that allow containers
// to use additional types of devices.
DeviceCGroupRule []spec.LinuxDeviceCgroup `json:"device_cgroup_rule,omitempty"`
+ // DevicesFrom is a way to ensure your container inherits device specific information from another container
+ DevicesFrom []string `json:"devices_from,omitempty"`
+ // HostDeviceList is used to recreate the mounted device on inherited containers
+ HostDeviceList []spec.LinuxDevice `json:"host_device_list,omitempty"`
// IpcNS is the container's IPC namespace.
// Default is private.
// Conflicts with ShmSize if not set to private.
diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go
index 0ed08198f..3ce96164f 100644
--- a/pkg/specgenutil/volumes.go
+++ b/pkg/specgenutil/volumes.go
@@ -243,7 +243,7 @@ func getBindMount(args []string) (spec.Mount, error) {
Type: define.TypeBind,
}
- var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel bool
+ var setSource, setDest, setRORW, setSuid, setDev, setExec, setRelabel, setOwnership bool
for _, val := range args {
kv := strings.SplitN(val, "=", 2)
@@ -343,6 +343,18 @@ func getBindMount(args []string) (spec.Mount, error) {
default:
return newMount, errors.Wrapf(util.ErrBadMntOption, "%s mount option must be 'private' or 'shared'", kv[0])
}
+ case "U", "chown":
+ if setOwnership {
+ return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once")
+ }
+ ok, err := validChownFlag(val)
+ if err != nil {
+ return newMount, err
+ }
+ if ok {
+ newMount.Options = append(newMount.Options, "U")
+ }
+ setOwnership = true
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
@@ -375,7 +387,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) {
Source: define.TypeTmpfs,
}
- var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup bool
+ var setDest, setRORW, setSuid, setDev, setExec, setTmpcopyup, setOwnership bool
for _, val := range args {
kv := strings.SplitN(val, "=", 2)
@@ -431,6 +443,18 @@ func getTmpfsMount(args []string) (spec.Mount, error) {
}
newMount.Destination = filepath.Clean(kv[1])
setDest = true
+ case "U", "chown":
+ if setOwnership {
+ return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once")
+ }
+ ok, err := validChownFlag(val)
+ if err != nil {
+ return newMount, err
+ }
+ if ok {
+ newMount.Options = append(newMount.Options, "U")
+ }
+ setOwnership = true
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
@@ -486,7 +510,7 @@ func getDevptsMount(args []string) (spec.Mount, error) {
func getNamedVolume(args []string) (*specgen.NamedVolume, error) {
newVolume := new(specgen.NamedVolume)
- var setSource, setDest, setRORW, setSuid, setDev, setExec bool
+ var setSource, setDest, setRORW, setSuid, setDev, setExec, setOwnership bool
for _, val := range args {
kv := strings.SplitN(val, "=", 2)
@@ -532,6 +556,18 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) {
}
newVolume.Dest = filepath.Clean(kv[1])
setDest = true
+ case "U", "chown":
+ if setOwnership {
+ return newVolume, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once")
+ }
+ ok, err := validChownFlag(val)
+ if err != nil {
+ return newVolume, err
+ }
+ if ok {
+ newVolume.Options = append(newVolume.Options, "U")
+ }
+ setOwnership = true
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
@@ -628,3 +664,24 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) {
}
return m, nil
}
+
+// validChownFlag ensures that the U or chown flag is correctly used
+func validChownFlag(flag string) (bool, error) {
+ kv := strings.SplitN(flag, "=", 2)
+ switch len(kv) {
+ case 1:
+ case 2:
+ // U=[true|false]
+ switch strings.ToLower(kv[1]) {
+ case "true":
+ case "false":
+ return false, nil
+ default:
+ return false, errors.Wrapf(optionArgError, "'U' or 'chown' must be set to true or false, instead received %q", kv[1])
+ }
+ default:
+ return false, errors.Wrapf(optionArgError, "badly formatted option %q", flag)
+ }
+
+ return true, nil
+}
diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go
index 18a6a1717..584d1fa02 100644
--- a/pkg/trust/trust.go
+++ b/pkg/trust/trust.go
@@ -188,7 +188,7 @@ func GetGPGIdFromKeyPath(path string) []string {
cmd := exec.Command("gpg2", "--with-colons", path)
results, err := cmd.Output()
if err != nil {
- logrus.Errorf("error getting key identity: %s", err)
+ logrus.Errorf("Getting key identity: %s", err)
return nil
}
return parseUids(results)
@@ -203,7 +203,7 @@ func GetGPGIdFromKeyData(key string) []string {
}
tmpfileName, err := CreateTmpFile("", "", decodeKey)
if err != nil {
- logrus.Errorf("error creating key date temp file %s", err)
+ logrus.Errorf("Creating key date temp file %s", err)
}
defer os.Remove(tmpfileName)
return GetGPGIdFromKeyPath(tmpfileName)
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 dbad6824f..853e9da88 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
@@ -56,7 +56,7 @@ class ContainerTestCase(APITestCase):
self.assertEqual(r.status_code, 200, r.text)
self.assertId(r.content)
out = r.json()
- self.assertIsNone(out["State"].get("Health"))
+ self.assertIsNotNone(out["State"].get("Health"))
self.assertListEqual(["CMD", "pidof", "top"], out["Config"]["Healthcheck"]["Test"])
self.assertEqual(5000000000, out["Config"]["Healthcheck"]["Interval"])
self.assertEqual(2000000000, out["Config"]["Healthcheck"]["Timeout"])
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py
index bcacaa935..58d03b149 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_image.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py
@@ -32,6 +32,9 @@ class ImageTestCase(APITestCase):
for k in required_keys:
self.assertIn(k, item)
+ # Id should be prefixed with sha256: (#11645)
+ self.assertIn("sha256:",item['Id'])
+
def test_inspect(self):
r = requests.get(self.podman_url + "/v1.40/images/alpine/json")
self.assertEqual(r.status_code, 200, r.text)
@@ -59,6 +62,8 @@ class ImageTestCase(APITestCase):
for item in required_keys:
self.assertIn(item, image)
_ = parse(image["Created"])
+ # Id should be prefixed with sha256: (#11645)
+ self.assertIn("sha256:",image['Id'])
def test_delete(self):
r = requests.delete(self.podman_url + "/v1.40/images/alpine?force=true")
diff --git a/test/compose/test-compose b/test/compose/test-compose
index 70db6dd55..beaf276fd 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -247,6 +247,7 @@ function podman() {
--storage-driver=vfs \
--root $WORKDIR/root \
--runroot $WORKDIR/runroot \
+ --cni-config-dir $WORKDIR/cni \
"$@")
echo -n "$output" >>$WORKDIR/output.log
}
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index fbd4068f8..d40faf54b 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -332,7 +332,7 @@ var _ = Describe("Podman commit", func() {
It("podman commit adds exposed ports", func() {
name := "testcon"
- s := podmanTest.Podman([]string{"run", "--name", name, "-p", "8080:80", ALPINE, "true"})
+ s := podmanTest.Podman([]string{"run", "--name", name, "-p", "8585:80", ALPINE, "true"})
s.WaitWithDefaultTimeout()
Expect(s).Should(Exit(0))
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 20ed72c59..7228682f3 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -311,7 +311,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
func (p PodmanTestIntegration) AddImageToRWStore(image string) {
if err := p.RestoreArtifact(image); err != nil {
- logrus.Errorf("unable to restore %s to RW store", image)
+ logrus.Errorf("Unable to restore %s to RW store", image)
}
}
diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf
index bbd712254..c33f32ab4 100644
--- a/test/e2e/config/containers.conf
+++ b/test/e2e/config/containers.conf
@@ -59,6 +59,7 @@ no_hosts=true
[engine]
network_cmd_options=["allow_host_loopback=true"]
+service_timeout=1234
# We need to ensure each test runs on a separate plugin instance...
# For now, let's just make a bunch of plugin paths and have each test use one.
diff --git a/test/e2e/container_inspect_test.go b/test/e2e/container_inspect_test.go
index 7d05b09fb..597eeb1a4 100644
--- a/test/e2e/container_inspect_test.go
+++ b/test/e2e/container_inspect_test.go
@@ -47,25 +47,25 @@ var _ = Describe("Podman container inspect", func() {
It("podman inspect shows exposed ports", func() {
name := "testcon"
- session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8080/udp", "--name", name, ALPINE, "sleep", "inf"})
+ session := podmanTest.Podman([]string{"run", "-d", "--stop-timeout", "0", "--expose", "8787/udp", "--name", name, ALPINE, "sleep", "inf"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
data := podmanTest.InspectContainer(name)
Expect(data).To(HaveLen(1))
Expect(data[0].NetworkSettings.Ports).
- To(Equal(map[string][]define.InspectHostPort{"8080/udp": nil}))
+ To(Equal(map[string][]define.InspectHostPort{"8787/udp": nil}))
})
It("podman inspect shows exposed ports on image", func() {
name := "testcon"
- session := podmanTest.Podman([]string{"run", "-d", "--expose", "8080", "--name", name, nginx})
+ session := podmanTest.Podman([]string{"run", "-d", "--expose", "8989", "--name", name, nginx})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
data := podmanTest.InspectContainer(name)
Expect(data).To(HaveLen(1))
Expect(data[0].NetworkSettings.Ports).
- To(Equal(map[string][]define.InspectHostPort{"80/tcp": nil, "8080/tcp": nil}))
+ To(Equal(map[string][]define.InspectHostPort{"80/tcp": nil, "8989/tcp": nil}))
})
})
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index f5e85e723..fac200c3c 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -444,4 +444,12 @@ var _ = Describe("Podman run", func() {
Expect(session).Should(Exit(0))
Expect(session.ErrorToString()).To(ContainSubstring("invalid image_copy_tmp_dir"))
})
+
+ It("podman system sevice --help shows (default 20)", func() {
+ SkipIfRemote("this test is only for local")
+ result := podmanTest.Podman([]string{"system", "service", "--help"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring("(default 1234)"))
+ })
})
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 32d98c2a9..d20dc8874 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -618,7 +618,7 @@ var _ = Describe("Podman create", func() {
pod.WaitWithDefaultTimeout()
Expect(pod).Should(Exit(0))
- session := podmanTest.Podman([]string{"create", "--pod", name, "-p", "8080:80", ALPINE, "top"})
+ session := podmanTest.Podman([]string{"create", "--pod", name, "-p", "8086:80", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitWithError())
})
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index bf89a0708..cb987e139 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -6,6 +6,8 @@ import (
"path/filepath"
"strconv"
+ "github.com/containers/podman/v3/libpod/define"
+
"github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
"github.com/ghodss/yaml"
@@ -555,6 +557,15 @@ var _ = Describe("Podman generate kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
+ b, err := ioutil.ReadFile(outputFile)
+ Expect(err).ShouldNot(HaveOccurred())
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal(b, pod)
+ Expect(err).To(BeNil())
+ val, found := pod.Annotations[define.BindMountPrefix+vol1]
+ Expect(found).To(BeTrue())
+ Expect(val).To(HaveSuffix("z"))
+
rm := podmanTest.Podman([]string{"pod", "rm", "-f", "test1"})
rm.WaitWithDefaultTimeout()
Expect(rm).Should(Exit(0))
@@ -792,6 +803,45 @@ var _ = Describe("Podman generate kube", func() {
Expect(containers[0].Args).To(Equal([]string{"10s"}))
})
+ It("podman generate kube - no command", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "test", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "test"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ // Now make sure that the container's command is not set to the
+ // entrypoint and it's arguments to "10s".
+ pod := new(v1.Pod)
+ err := yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers := pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(len(containers[0].Command)).To(Equal(0))
+
+ cmd := []string{"echo", "hi"}
+ session = podmanTest.Podman(append([]string{"create", "--name", "test1", ALPINE}, cmd...))
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "test1"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ // Now make sure that the container's command is not set to the
+ // entrypoint and it's arguments to "10s".
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers = pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(containers[0].Command).To(Equal(cmd))
+ })
+
It("podman generate kube - use entrypoint from image", func() {
// Build an image with an entrypoint.
containerfile := `FROM quay.io/libpod/alpine:latest
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index 87f042ed9..b2666c789 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -80,6 +80,11 @@ var _ = Describe("Podman healthcheck run", func() {
time.Sleep(1 * time.Second)
}
Expect(exitCode).To(Equal(0))
+
+ ps := podmanTest.Podman([]string{"ps"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps).Should(Exit(0))
+ Expect(ps.OutputToString()).To(ContainSubstring("(healthy)"))
})
It("podman healthcheck that should fail", func() {
@@ -117,7 +122,7 @@ var _ = Describe("Podman healthcheck run", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting"))
+ Expect(inspect[0].State.Health.Status).To(Equal("starting"))
})
It("podman healthcheck failed checks in start-period should not change status", func() {
@@ -138,7 +143,9 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(1))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting"))
+ Expect(inspect[0].State.Health.Status).To(Equal("starting"))
+ // test old podman compat (see #11645)
+ Expect(inspect[0].State.Healthcheck().Status).To(Equal("starting"))
})
It("podman healthcheck failed checks must reach retries before unhealthy ", func() {
@@ -151,15 +158,16 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(1))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting"))
+ Expect(inspect[0].State.Health.Status).To(Equal("starting"))
hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"})
hc.WaitWithDefaultTimeout()
Expect(hc).Should(Exit(1))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy))
-
+ Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy))
+ // test old podman compat (see #11645)
+ Expect(inspect[0].State.Healthcheck().Status).To(Equal(define.HealthCheckUnhealthy))
})
It("podman healthcheck good check results in healthy even in start-period", func() {
@@ -172,7 +180,7 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(0))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy))
+ Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy))
})
It("podman healthcheck unhealthy but valid arguments check", func() {
@@ -195,14 +203,14 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(1))
inspect := podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal("starting"))
+ Expect(inspect[0].State.Health.Status).To(Equal("starting"))
hc = podmanTest.Podman([]string{"healthcheck", "run", "hc"})
hc.WaitWithDefaultTimeout()
Expect(hc).Should(Exit(1))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckUnhealthy))
+ Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckUnhealthy))
foo := podmanTest.Podman([]string{"exec", "hc", "touch", "/foo"})
foo.WaitWithDefaultTimeout()
@@ -213,6 +221,13 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(0))
inspect = podmanTest.InspectContainer("hc")
- Expect(inspect[0].State.Healthcheck.Status).To(Equal(define.HealthCheckHealthy))
+ Expect(inspect[0].State.Health.Status).To(Equal(define.HealthCheckHealthy))
+
+ // Test podman ps --filter heath is working (#11687)
+ ps := podmanTest.Podman([]string{"ps", "--filter", "health=healthy"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps).Should(Exit(0))
+ Expect(len(ps.OutputToStringArray())).To(Equal(2))
+ Expect(ps.OutputToString()).To(ContainSubstring("hc"))
})
})
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index 12165d92d..63a54a5ca 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -451,14 +451,14 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect --format json .NetworkSettings.Ports", func() {
ctnrName := "Ctnr_" + RandomString(25)
- create := podmanTest.Podman([]string{"create", "--name", ctnrName, "-p", "8080:80", ALPINE})
+ create := podmanTest.Podman([]string{"create", "--name", ctnrName, "-p", "8084:80", ALPINE})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
inspect := podmanTest.Podman([]string{"inspect", `--format="{{json .NetworkSettings.Ports}}"`, ctnrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
- Expect(inspect.OutputToString()).To(Equal(`"{"80/tcp":[{"HostIp":"","HostPort":"8080"}]}"`))
+ Expect(inspect.OutputToString()).To(Equal(`"{"80/tcp":[{"HostIp":"","HostPort":"8084"}]}"`))
})
It("Verify container inspect has default network", func() {
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index 217efdeec..5f7c55d3f 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -52,7 +52,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network disconnect with net mode slirp4netns should result in error", func() {
- SkipIfRootless("network connect and disconnect are only rootful")
netName := "slirp" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -118,7 +117,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network connect with net mode slirp4netns should result in error", func() {
- SkipIfRootless("network connect and disconnect are only rootful")
netName := "slirp" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -146,6 +144,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
Expect(ctr).Should(Exit(0))
+ cid := ctr.OutputToString()
+
+ // network alias container short id is always added and shown in inspect
+ inspect := podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + netName + "\").Aliases}}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]"))
con := podmanTest.Podman([]string{"network", "connect", netName, "test"})
con.WaitWithDefaultTimeout()
@@ -153,7 +158,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network connect", func() {
- SkipIfRemote("This requires a pending PR to be merged before it will work")
netName := "aliasTest" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -163,6 +167,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
Expect(ctr).Should(Exit(0))
+ cid := ctr.OutputToString()
exec := podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth0"})
exec.WaitWithDefaultTimeout()
@@ -184,6 +189,12 @@ var _ = Describe("Podman network connect and disconnect", func() {
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(Equal("2"))
+ // network alias container short id is always added and shown in inspect
+ inspect = podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + newNetName + "\").Aliases}}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]"))
+
exec = podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth1"})
exec.WaitWithDefaultTimeout()
Expect(exec).Should(Exit(0))
@@ -193,7 +204,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
rm.WaitWithDefaultTimeout()
Expect(rm).Should(Exit(0))
Expect(rm.ErrorToString()).To(Equal(""))
-
})
It("podman network connect when not running", func() {
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 7e56b8a25..8e47fac75 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -603,6 +603,11 @@ var _ = Describe("Podman network", func() {
})
It("podman network prune --filter", func() {
+ // set custom cni directory to prevent flakes
+ podmanTest.CNIConfigDir = tempdir
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ }
net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1"
nc := podmanTest.Podman([]string{"network", "create", net1})
@@ -613,11 +618,10 @@ var _ = Describe("Podman network", func() {
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
// -f needed only to skip y/n question
prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=50"})
@@ -627,11 +631,10 @@ var _ = Describe("Podman network", func() {
listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
// -f needed only to skip y/n question
prune = podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=5000000000000"})
@@ -641,14 +644,18 @@ var _ = Describe("Podman network", func() {
listAgain = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(1))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
})
It("podman network prune", func() {
+ // set custom cni directory to prevent flakes
+ podmanTest.CNIConfigDir = tempdir
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ }
// Create two networks
// Check they are there
// Run a container on one of them
@@ -669,13 +676,11 @@ var _ = Describe("Podman network", func() {
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
list.WaitWithDefaultTimeout()
- Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).Should(HaveLen(3))
- Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
- Expect(StringInSlice(net2, list.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(list.OutputToStringArray()).Should(ContainElement(net2))
+ Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
session := podmanTest.Podman([]string{"run", "-dt", "--net", net2, ALPINE, "top"})
session.WaitWithDefaultTimeout()
@@ -688,13 +693,10 @@ var _ = Describe("Podman network", func() {
listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
- Expect(StringInSlice(net2, listAgain.OutputToStringArray())).To(BeTrue())
- // Make sure default network 'podman' still exists
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
-
+ Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement(net2))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
})
})
diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go
index 16f2687f3..564735e07 100644
--- a/test/e2e/play_build_test.go
+++ b/test/e2e/play_build_test.go
@@ -80,12 +80,17 @@ status: {}
FROM quay.io/libpod/alpine_nginx:latest
RUN apk update && apk add strace
LABEL homer=dad
+COPY copyfile /copyfile
`
var prebuiltImage = `
FROM quay.io/libpod/alpine_nginx:latest
RUN apk update && apk add strace
LABEL marge=mom
`
+
+ var copyFile = `just a text file
+`
+
It("Check that image is built using Dockerfile", func() {
// Setup
yamlDir := filepath.Join(tempdir, RandomString(12))
@@ -97,7 +102,9 @@ LABEL marge=mom
Expect(err).To(BeNil())
err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Dockerfile"))
Expect(err).To(BeNil())
-
+ // Write a file to be copied
+ err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile"))
+ Expect(err).To(BeNil())
// Switch to temp dir and restore it afterwards
cwd, err := os.Getwd()
Expect(err).To(BeNil())
@@ -131,7 +138,9 @@ LABEL marge=mom
Expect(err).To(BeNil())
err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile"))
Expect(err).To(BeNil())
-
+ // Write a file to be copied
+ err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile"))
+ Expect(err).To(BeNil())
// Switch to temp dir and restore it afterwards
cwd, err := os.Getwd()
Expect(err).To(BeNil())
@@ -172,6 +181,9 @@ LABEL marge=mom
Expect(err).To(BeNil())
err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile"))
Expect(err).To(BeNil())
+ // Write a file to be copied
+ err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile"))
+ Expect(err).To(BeNil())
// Switch to temp dir and restore it afterwards
cwd, err := os.Getwd()
@@ -215,6 +227,9 @@ LABEL marge=mom
Expect(err).To(BeNil())
err = writeYaml(playBuildFile, filepath.Join(app1Dir, "Containerfile"))
Expect(err).To(BeNil())
+ // Write a file to be copied
+ err = writeYaml(copyFile, filepath.Join(app1Dir, "copyfile"))
+ Expect(err).To(BeNil())
// Switch to temp dir and restore it afterwards
cwd, err := os.Getwd()
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index fcda89fbc..83ce751e6 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -63,12 +63,6 @@ spec:
- -d
- "1.5"
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- - name: container
- value: podman
- name: HOSTNAME
value: label-pod
image: quay.io/libpod/alpine:latest
@@ -171,12 +165,6 @@ spec:
- -d
- "1.5"
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- - name: container
- value: podman
- name: HOSTNAME
value: label-pod
image: quay.io/libpod/alpine:latest
@@ -287,13 +275,7 @@ spec:
- {{.}}
{{ end }}
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- name: HOSTNAME
- - name: container
- value: podman
{{ range .Env }}
- name: {{ .Name }}
{{ if (eq .ValueFrom "configmap") }}
@@ -453,13 +435,7 @@ spec:
- {{.}}
{{ end }}
env:
- - name: PATH
- value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- - name: TERM
- value: xterm
- name: HOSTNAME
- - name: container
- value: podman
image: {{ .Image }}
name: {{ .Name }}
imagePullPolicy: {{ .PullPolicy }}
@@ -2344,6 +2320,39 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
}
})
+ It("podman play kube allows setting resource limits with --cpus 1", func() {
+ SkipIfContainerized("Resource limits require a running systemd")
+ SkipIfRootless("CPU limits require root")
+ podmanTest.CgroupManager = "systemd"
+
+ var (
+ expectedCpuLimit string = "1"
+ )
+
+ deployment := getDeployment(
+ withPod(getPod(withCtr(getCtr(
+ withCpuLimit(expectedCpuLimit),
+ )))))
+ err := generateKubeYaml("deployment", deployment, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ for _, pod := range getPodNamesInDeployment(deployment) {
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&pod), "--format", `{{ .HostConfig.CpuPeriod }}:{{ .HostConfig.CpuQuota }}`})
+
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+
+ parts := strings.Split(strings.Trim(inspect.OutputToString(), "\n"), ":")
+ Expect(parts).To(HaveLen(2))
+
+ Expect(parts[0]).To(Equal(parts[1]))
+ }
+ })
+
It("podman play kube reports invalid image name", func() {
invalidImageName := "./myimage"
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 7d40d36dd..c9924be72 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -108,7 +108,7 @@ 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", "8080:80"})
+ session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8081:80"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
pod := session.OutputToString()
@@ -117,14 +117,14 @@ var _ = Describe("Podman pod create", func() {
webserver.WaitWithDefaultTimeout()
Expect(webserver).Should(Exit(0))
- check := SystemExec("nc", []string{"-z", "localhost", "8080"})
+ check := SystemExec("nc", []string{"-z", "localhost", "8081"})
Expect(check).Should(Exit(0))
})
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", "8080:80"})
+ session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8082:80"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -132,7 +132,7 @@ var _ = Describe("Podman pod create", func() {
webserver.WaitWithDefaultTimeout()
Expect(webserver).Should(Exit(0))
- check := SystemExec("nc", []string{"-z", "localhost", "8080"})
+ check := SystemExec("nc", []string{"-z", "localhost", "8082"})
Expect(check).Should(Exit(0))
})
@@ -881,6 +881,25 @@ ENTRYPOINT ["sleep","99999"]
ctr3 := podmanTest.Podman([]string{"run", "--pod", podName, ALPINE, "cat", "/tmp1/test"})
ctr3.WaitWithDefaultTimeout()
Expect(ctr3.OutputToString()).To(ContainSubstring("hello"))
+ })
+
+ It("podman pod create --device", func() {
+ SkipIfRootless("Cannot create devices in /dev in rootless mode")
+ Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
+ defer os.RemoveAll("/dev/foodevdir")
+
+ mknod := SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"})
+ mknod.WaitWithDefaultTimeout()
+ Expect(mknod).Should(Exit(0))
+
+ podName := "testPod"
+ session := podmanTest.Podman([]string{"pod", "create", "--device", "/dev/foodevdir:/dev/bar", "--name", podName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"run", "-q", "--pod", podName, ALPINE, "stat", "-c%t:%T", "/dev/bar/null"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal("1:3"))
})
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 6633b228c..5728cf9b9 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -85,7 +85,7 @@ var _ = Describe("Podman pod inspect", func() {
It("podman pod inspect outputs port bindings", func() {
podName := "testPod"
- create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "8080:80"})
+ create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "8383:80"})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
@@ -98,7 +98,7 @@ var _ = Describe("Podman pod inspect", func() {
Expect(err).To(BeNil())
Expect(inspectJSON.InfraConfig).To(Not(BeNil()))
Expect(len(inspectJSON.InfraConfig.PortBindings["80/tcp"])).To(Equal(1))
- Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectJSON.InfraConfig.PortBindings["80/tcp"][0].HostPort).To(Equal("8383"))
})
It("podman pod inspect outputs show correct MAC", func() {
diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go
index 93c200389..e895b5598 100644
--- a/test/e2e/pod_start_test.go
+++ b/test/e2e/pod_start_test.go
@@ -92,7 +92,7 @@ var _ = Describe("Podman pod start", func() {
pod, _, podid1 := podmanTest.CreatePod(map[string][]string{
"--infra": {"true"},
"--name": {podName[0]},
- "--publish": {"127.0.0.1:8080:80"},
+ "--publish": {"127.0.0.1:8083:80"},
})
Expect(pod).To(Exit(0))
@@ -103,7 +103,7 @@ var _ = Describe("Podman pod start", func() {
pod, _, podid2 := podmanTest.CreatePod(map[string][]string{
"--infra": {"true"},
"--name": {podName[1]},
- "--publish": {"127.0.0.1:8080:80"},
+ "--publish": {"127.0.0.1:8083:80"},
})
Expect(pod).To(Exit(0))
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index aeb88e481..881d9fcf0 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -6,7 +6,6 @@ import (
"regexp"
"sort"
"strconv"
- "strings"
. "github.com/containers/podman/v3/test/utils"
"github.com/containers/storage/pkg/stringid"
@@ -187,7 +186,10 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("bravo"))
+
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("bravo"))
+ Expect(actual).To(ContainSubstring("NAMES"))
})
It("podman ps --filter network=container:<id>", func() {
@@ -206,7 +208,9 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("second"))
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("second"))
+ Expect(actual).ToNot(ContainSubstring("table"))
})
It("podman ps namespace flag", func() {
@@ -228,7 +232,7 @@ var _ = Describe("Podman ps", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
// it must contains `::` when some ns is null. If it works normally, it should be "$num1:$num2:$num3"
- Expect(result.OutputToString()).To(Not(ContainSubstring(`::`)))
+ Expect(result.OutputToString()).ToNot(ContainSubstring(`::`))
})
It("podman ps with no containers is valid json format", func() {
@@ -285,11 +289,14 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.ImageID}} {{.Labels}}"})
result.WaitWithDefaultTimeout()
-
- Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("table"))
- Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("ImageID"))
- Expect(result.OutputToStringArray()[0]).To(ContainSubstring("alpine:latest"))
Expect(result).Should(Exit(0))
+
+ Expect(result.OutputToString()).ToNot(ContainSubstring("table"))
+
+ actual := result.OutputToStringArray()
+ Expect(actual[0]).To(ContainSubstring("CONTAINER ID"))
+ Expect(actual[0]).ToNot(ContainSubstring("ImageID"))
+ Expect(actual[1]).To(ContainSubstring("alpine:latest"))
})
It("podman ps ancestor filter flag", func() {
@@ -380,7 +387,9 @@ var _ = Describe("Podman ps", func() {
psFilter.WaitWithDefaultTimeout()
Expect(psFilter).Should(Exit(0))
- Expect(strings.Contains(psFilter.OutputToString(), ctrName)).To(BeFalse())
+ actual := psFilter.OutputToString()
+ Expect(actual).ToNot(ContainSubstring(ctrName))
+ Expect(actual).ToNot(ContainSubstring("NAMES"))
})
It("podman ps mutually exclusive flags", func() {
@@ -453,14 +462,13 @@ var _ = Describe("Podman ps", func() {
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"ps", "-a", "--sort=command", "--format", "{{.Command}}"})
-
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- sortedArr := session.OutputToStringArray()
+ Expect(session.OutputToString()).ToNot(ContainSubstring("COMMAND"))
+ sortedArr := session.OutputToStringArray()
Expect(sort.SliceIsSorted(sortedArr, func(i, j int) bool { return sortedArr[i] < sortedArr[j] })).To(BeTrue())
-
})
It("podman --pod", func() {
@@ -474,7 +482,7 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--no-trunc"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Not(ContainSubstring(podid)))
+ Expect(session.OutputToString()).ToNot(ContainSubstring(podid))
session = podmanTest.Podman([]string{"ps", "--pod", "--no-trunc"})
session.WaitWithDefaultTimeout()
@@ -510,7 +518,11 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"})
session.WaitWithDefaultTimeout()
- Expect(session.OutputToString()).To(ContainSubstring("0.0.0.0:2000-2006"))
+ Expect(session).To(Exit(0))
+
+ actual := session.OutputToString()
+ Expect(actual).To(ContainSubstring("0.0.0.0:2000-2006"))
+ Expect(actual).ToNot(ContainSubstring("PORT"))
})
It("podman ps test with invalid port range", func() {
@@ -597,7 +609,7 @@ var _ = Describe("Podman ps", func() {
It("podman ps test with port shared with pod", func() {
podName := "testPod"
- pod := podmanTest.Podman([]string{"pod", "create", "-p", "8080:80", "--name", podName})
+ pod := podmanTest.Podman([]string{"pod", "create", "-p", "8085:80", "--name", podName})
pod.WaitWithDefaultTimeout()
Expect(pod).Should(Exit(0))
@@ -609,7 +621,7 @@ var _ = Describe("Podman ps", func() {
ps := podmanTest.Podman([]string{"ps", "--filter", fmt.Sprintf("name=%s", ctrName), "--format", "{{.Ports}}"})
ps.WaitWithDefaultTimeout()
Expect(ps).Should(Exit(0))
- Expect(ps.OutputToString()).To(ContainSubstring("0.0.0.0:8080->80/tcp"))
+ Expect(ps.OutputToString()).To(ContainSubstring("0.0.0.0:8085->80/tcp"))
})
It("podman ps truncate long create command", func() {
@@ -628,7 +640,10 @@ var _ = Describe("Podman ps", func() {
result := podmanTest.Podman([]string{"ps", "-a", "--format", "{{.RunningFor}}"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(ContainSubstring("ago"))
+
+ actual := result.OutputToString()
+ Expect(actual).To(ContainSubstring("ago"))
+ Expect(actual).ToNot(ContainSubstring("RUNNING FOR"))
})
It("podman ps filter test", func() {
@@ -823,8 +838,9 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--no-trunc", "--filter", "network=" + net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(ContainSubstring(ctrWithNet))
- Expect(session.OutputToString()).To(Not(ContainSubstring(ctrWithoutNet)))
+ actual := session.OutputToString()
+ Expect(actual).To(ContainSubstring(ctrWithNet))
+ Expect(actual).ToNot(ContainSubstring(ctrWithoutNet))
})
It("podman ps --format networks", func() {
@@ -835,12 +851,15 @@ var _ = Describe("Podman ps", func() {
session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+
+ actual := session.OutputToString()
+ Expect(actual).ToNot(ContainSubstring("NETWORKS"))
if isRootless() {
// rootless container don't have a network by default
- Expect(session.OutputToString()).To(Equal(""))
+ Expect(actual).To(BeEmpty())
} else {
// default network name is podman
- Expect(session.OutputToString()).To(Equal("podman"))
+ Expect(actual).To(Equal("podman"))
}
net1 := stringid.GenerateNonCryptoID()
diff --git a/test/e2e/rename_test.go b/test/e2e/rename_test.go
index 0bd1792c9..e5e69c25c 100644
--- a/test/e2e/rename_test.go
+++ b/test/e2e/rename_test.go
@@ -111,4 +111,29 @@ var _ = Describe("podman rename", func() {
Expect(ps).Should(Exit(0))
Expect(ps.OutputToString()).To(ContainSubstring(newName))
})
+
+ It("Rename a container that is part of a pod", func() {
+ podName := "testPod"
+ infraName := "infra1"
+ pod := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--infra-name", infraName})
+ pod.WaitWithDefaultTimeout()
+ Expect(pod).Should(Exit(0))
+
+ infraName2 := "infra2"
+ rename := podmanTest.Podman([]string{"rename", infraName, infraName2})
+ rename.WaitWithDefaultTimeout()
+ Expect(rename).Should(Exit(0))
+
+ remove := podmanTest.Podman([]string{"pod", "rm", "-f", podName})
+ remove.WaitWithDefaultTimeout()
+ Expect(remove).Should(Exit(0))
+
+ create := podmanTest.Podman([]string{"create", "--name", infraName2, ALPINE, "top"})
+ create.WaitWithDefaultTimeout()
+ Expect(create).Should(Exit(0))
+
+ create2 := podmanTest.Podman([]string{"create", "--name", infraName, ALPINE, "top"})
+ create2.WaitWithDefaultTimeout()
+ Expect(create2).Should(Exit(0))
+ })
})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index c7ffdaf4c..84707732b 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -98,9 +98,9 @@ var _ = Describe("Podman run networking", func() {
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 80-82 -p 8080:8080", func() {
+ It("podman run -p 80-82 -p 8090:8090", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "80-82", "-p", "8080:8080", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "80-82", "-p", "8090:8090", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
@@ -114,14 +114,14 @@ var _ = Describe("Podman run networking", func() {
Expect(len(inspectOut[0].NetworkSettings.Ports["82/tcp"])).To(Equal(1))
Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostPort).To(Not(Equal("82")))
Expect(inspectOut[0].NetworkSettings.Ports["82/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Equal("8080"))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8090/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostPort).To(Equal("8090"))
+ Expect(inspectOut[0].NetworkSettings.Ports["8090/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 80-81 -p 8080-8081", func() {
+ It("podman run -p 80-81 -p 8180-8181", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "80-81", "-p", "8080-8081", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "80-81", "-p", "8180-8181", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
@@ -132,17 +132,17 @@ var _ = Describe("Podman run networking", func() {
Expect(len(inspectOut[0].NetworkSettings.Ports["81/tcp"])).To(Equal(1))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostPort).To(Not(Equal("81")))
Expect(inspectOut[0].NetworkSettings.Ports["81/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080")))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8081/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostPort).To(Not(Equal("8081")))
- Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8180/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostPort).To(Not(Equal("8180")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8180/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 80 -p 8080-8082:8080-8082", func() {
+ It("podman run -p 80 -p 8280-8282:8280-8282", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "-p", "8080-8082:8080-8082", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "80", "-p", "8280-8282:8280-8282", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
@@ -150,40 +150,40 @@ var _ = Describe("Podman run networking", func() {
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("80")))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Equal("8080"))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8081/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostPort).To(Equal("8081"))
- Expect(inspectOut[0].NetworkSettings.Ports["8081/tcp"][0].HostIP).To(Equal(""))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8082/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8082/tcp"][0].HostPort).To(Equal("8082"))
- Expect(inspectOut[0].NetworkSettings.Ports["8082/tcp"][0].HostIP).To(Equal(""))
- })
-
- It("podman run -p 8080:80", func() {
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8280/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostPort).To(Equal("8280"))
+ Expect(inspectOut[0].NetworkSettings.Ports["8280/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8281/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostPort).To(Equal("8281"))
+ Expect(inspectOut[0].NetworkSettings.Ports["8281/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8282/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostPort).To(Equal("8282"))
+ Expect(inspectOut[0].NetworkSettings.Ports["8282/tcp"][0].HostIP).To(Equal(""))
+ })
+
+ It("podman run -p 8380:80", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "8080:80", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "8380:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8380"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 8080:80/TCP", func() {
+ It("podman run -p 8480:80/TCP", func() {
name := "testctr"
// "TCP" in upper characters
- session := podmanTest.Podman([]string{"create", "-t", "-p", "8080:80/TCP", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "8480:80/TCP", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
// "tcp" in lower characters
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8480"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -199,51 +199,51 @@ var _ = Describe("Podman run networking", func() {
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 127.0.0.1:8080:80", func() {
+ It("podman run -p 127.0.0.1:8580:80", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8080:80", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8580:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8580"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("127.0.0.1"))
})
- It("podman run -p 127.0.0.1:8080:80/udp", func() {
+ It("podman run -p 127.0.0.1:8680:80/udp", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8080:80/udp", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1:8680:80/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8680"))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("127.0.0.1"))
})
- It("podman run -p [::1]:8080:80/udp", func() {
+ It("podman run -p [::1]:8780:80/udp", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8080:80/udp", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8780:80/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8780"))
Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("::1"))
})
- It("podman run -p [::1]:8080:80/tcp", func() {
+ It("podman run -p [::1]:8880:80/tcp", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8080:80/tcp", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "[::1]:8880:80/tcp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8880"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("::1"))
})
@@ -283,33 +283,33 @@ var _ = Describe("Podman run networking", func() {
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 127.0.0.1::8080/udp", func() {
+ It("podman run -p 127.0.0.1::8980/udp", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8080/udp", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8980/udp", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/udp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostPort).To(Not(Equal("8080")))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostIP).To(Equal("127.0.0.1"))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8980/udp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostPort).To(Not(Equal("8980")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8980/udp"][0].HostIP).To(Equal("127.0.0.1"))
})
- It("podman run -p :8080", func() {
+ It("podman run -p :8181", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", ":8080", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", ":8181", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
- Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080")))
- Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8181/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostPort).To(Not(Equal("8181")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8181/tcp"][0].HostIP).To(Equal(""))
})
- It("podman run -p 8080:8080 -p 8081:8080", func() {
+ It("podman run -p xxx:8080 -p yyy:8080", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "4000:8080", "-p", "8000:8080", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "4444:8080", "-p", "5555:8080", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
@@ -320,18 +320,18 @@ var _ = Describe("Podman run networking", func() {
hp2 := inspectOut[0].NetworkSettings.Ports["8080/tcp"][1].HostPort
// We can't guarantee order
- Expect((hp1 == "4000" && hp2 == "8000") || (hp1 == "8000" && hp2 == "4000")).To(BeTrue())
+ Expect((hp1 == "4444" && hp2 == "5555") || (hp1 == "5555" && hp2 == "4444")).To(BeTrue())
})
- It("podman run -p 0.0.0.0:8080:80", func() {
+ It("podman run -p 0.0.0.0:9280:80", func() {
name := "testctr"
- session := podmanTest.Podman([]string{"create", "-t", "-p", "0.0.0.0:8080:80", "--name", name, ALPINE, "/bin/sh"})
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "0.0.0.0:9280:80", "--name", name, ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
inspectOut := podmanTest.InspectContainer(name)
Expect(len(inspectOut)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1))
- Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080"))
+ Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("9280"))
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
@@ -348,20 +348,20 @@ var _ = Describe("Podman run networking", func() {
Expect(ncBusy).To(ExitWithError())
})
- It("podman run network expose host port 8081 to container port 8000 using rootlesskit port handler", func() {
- session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", "8081:8000", ALPINE, "/bin/sh"})
+ 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)
Expect(session).Should(Exit(0))
- ncBusy := SystemExec("nc", []string{"-l", "-p", "8081"})
+ ncBusy := SystemExec("nc", []string{"-l", "-p", "18081"})
Expect(ncBusy).To(ExitWithError())
})
- It("podman run network expose host port 8082 to container port 8000 using slirp4netns port handler", func() {
- session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=slirp4netns", "-dt", "-p", "8082:8000", ALPINE, "/bin/sh"})
+ It("podman run network expose host port 18082 to container port 8000 using slirp4netns port handler", func() {
+ session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=slirp4netns", "-dt", "-p", "18082:8000", ALPINE, "/bin/sh"})
session.Wait(30)
Expect(session).Should(Exit(0))
- ncBusy := SystemExec("nc", []string{"-l", "-p", "8082"})
+ ncBusy := SystemExec("nc", []string{"-l", "-p", "18082"})
Expect(ncBusy).To(ExitWithError())
})
@@ -650,13 +650,13 @@ var _ = Describe("Podman run networking", func() {
defer podmanTest.removeCNINetwork(netName)
name := "nc-server"
- run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "8080"})
+ run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "9480"})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
// NOTE: we force the k8s-file log driver to make sure the
// tests are passing inside a container.
- run = podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "--rm", "--net", netName, "--uidmap", "0:1:4096", ALPINE, "sh", "-c", fmt.Sprintf("echo podman | nc -w 1 %s.dns.podman 8080", name)})
+ run = podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "--rm", "--net", netName, "--uidmap", "0:1:4096", ALPINE, "sh", "-c", fmt.Sprintf("echo podman | nc -w 1 %s.dns.podman 9480", name)})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index ec4b0d997..b6743f4b7 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1148,11 +1148,11 @@ USER mail`, BB)
})
It("podman run --pod automatically", func() {
- session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8080"})
+ session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8080"})
+ session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8686"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 59937b6c0..f1baa7780 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -242,6 +242,39 @@ var _ = Describe("Podman run with volumes", func() {
Expect(session).Should(Exit(0))
})
+ It("podman support overlay on named volume", 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")
+ }
+ }
+ 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 overlayed volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlayed"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // volume should contain only `test` not `overlayed`
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlayed")))
+ 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()
@@ -614,7 +647,7 @@ VOLUME /test/`, ALPINE)
Expect(len(session.OutputToStringArray())).To(Equal(2))
})
- It("podman run with U volume flag", func() {
+ It("podman run with --volume and U flag", func() {
SkipIfRemote("Overlay volumes only work locally")
u, err := user.Current()
@@ -665,6 +698,65 @@ VOLUME /test/`, ALPINE)
Expect(found).Should(BeTrue())
})
+ It("podman run with --mount and U flag", func() {
+ u, err := user.Current()
+ Expect(err).To(BeNil())
+ name := u.Username
+ if name == "root" {
+ name = "containers"
+ }
+
+ content, err := ioutil.ReadFile("/etc/subuid")
+ if err != nil {
+ Skip("cannot read /etc/subuid")
+ }
+
+ if !strings.Contains(string(content), name) {
+ Skip("cannot find mappings for the current user")
+ }
+
+ mountPath := filepath.Join(podmanTest.TempDir, "foo")
+ os.Mkdir(mountPath, 0755)
+
+ // false bind mount
+ vol := "type=bind,src=" + mountPath + ",dst=" + dest + ",U=false"
+ session := podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).ShouldNot(Equal("888:888"))
+
+ // invalid bind mount
+ vol = "type=bind,src=" + mountPath + ",dst=" + dest + ",U=invalid"
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).To(ExitWithError())
+
+ // true bind mount
+ vol = "type=bind,src=" + mountPath + ",dst=" + dest + ",U=true"
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("888:888"))
+
+ // tmpfs mount
+ vol = "type=tmpfs," + "dst=" + dest + ",chown"
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("888:888"))
+
+ // named volume mount
+ namedVolume := podmanTest.Podman([]string{"volume", "create", "foo"})
+ namedVolume.WaitWithDefaultTimeout()
+ Expect(namedVolume).Should(Exit(0))
+
+ vol = "type=volume,src=foo,dst=" + dest + ",chown=true"
+ session = podmanTest.Podman([]string{"run", "--rm", "--user", "888:888", "--mount", vol, ALPINE, "stat", "-c", "%u:%g", dest})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("888:888"))
+ })
+
It("volume permissions after run", func() {
imgName := "testimg"
dockerfile := fmt.Sprintf(`FROM %s
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index a984bf6d0..7f178d719 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -234,6 +234,17 @@ var _ = Describe("Podman stop", func() {
Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal(""))
})
+ It("podman stop should return silent success on stopping configured containers", func() {
+ // following container is not created on OCI runtime
+ // so we return success and assume that is is stopped
+ session2 := podmanTest.Podman([]string{"create", "--name", "stopctr", ALPINE, "/bin/sh"})
+ session2.WaitWithDefaultTimeout()
+ Expect(session2).Should(Exit(0))
+ session3 := podmanTest.Podman([]string{"stop", "stopctr"})
+ session3.WaitWithDefaultTimeout()
+ Expect(session3).Should(Exit(0))
+ })
+
It("podman stop --cidfile", func() {
tmpDir, err := ioutil.TempDir("", "")
diff --git a/test/e2e/system_connection_test.go b/test/e2e/system_connection_test.go
index 21398887a..6cdb78c5e 100644
--- a/test/e2e/system_connection_test.go
+++ b/test/e2e/system_connection_test.go
@@ -138,7 +138,7 @@ var _ = Describe("podman system connection", func() {
It("add tcp", func() {
cmd := []string{"system", "connection", "add",
"QA-TCP",
- "tcp://localhost:8080",
+ "tcp://localhost:8888",
}
session := podmanTest.Podman(cmd)
session.WaitWithDefaultTimeout()
@@ -150,7 +150,7 @@ var _ = Describe("podman system connection", func() {
Expect(cfg.Engine.ActiveService).To(Equal("QA-TCP"))
Expect(cfg.Engine.ServiceDestinations["QA-TCP"]).To(Equal(
config.Destination{
- URI: "tcp://localhost:8080",
+ URI: "tcp://localhost:8888",
Identity: "",
},
))
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index 3cf6244b6..93c4f3f12 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -73,6 +73,12 @@ var _ = Describe("Podman top", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
+
+ // Just a smoke test since groups may change over time.
+ result = podmanTest.Podman([]string{"container", "top", "test", "groups", "hgroups"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
})
It("podman top with options", func() {
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 963c89281..888c075b8 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -57,6 +57,9 @@ function setup() {
# Now untag the digest reference again.
run_podman untag $IMAGE $IMAGE@$digest
+
+ # Make sure the original image is still present (#11557).
+ run_podman image exists $IMAGE
}
# PR #7212: allow --remote anywhere before subcommand, not just as 1st flag
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index a04d2ac74..76ce12b81 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -135,31 +135,38 @@ function _log_test_until() {
s_after="after_$(random_string)_${driver}"
before=$(date --iso-8601=seconds)
- sleep 5
+ sleep 1
run_podman run --log-driver=$driver -d --name test $IMAGE sh -c \
"echo $s_before; trap 'echo $s_after; exit' SIGTERM; while :; do sleep 1; done"
# sleep a second to make sure the date is after the first echo
sleep 1
run_podman stop test
- # sleep for 20 seconds to get the proper after time
- sleep 20
+ run_podman wait test
- run_podman logs test
- is "$output" \
- "$s_before
+ # Sigh. Stupid journald has a lag. Wait a few seconds for it to catch up.
+ retries=20
+ s_both="$s_before
$s_after"
+ while [[ $retries -gt 0 ]]; do
+ run_podman logs test
+ if [[ "$output" = "$s_both" ]]; then
+ break
+ fi
+ retries=$((retries - 1))
+ sleep 0.1
+ done
+ if [[ $retries -eq 0 ]]; then
+ die "Timed out waiting for before&after in podman logs: $output"
+ fi
run_podman logs --until $before test
- is "$output" \
- ""
+ is "$output" "" "podman logs --until before"
- after=$(date --iso-8601=seconds)
+ after=$(date --date='+1 second' --iso-8601=seconds)
run_podman logs --until $after test
- is "$output" \
- "$s_before
-$s_after"
+ is "$output" "$s_both" "podman logs --until after"
run_podman rm -f test
}
diff --git a/test/system/040-ps.bats b/test/system/040-ps.bats
index 182d75547..63f57efdc 100644
--- a/test/system/040-ps.bats
+++ b/test/system/040-ps.bats
@@ -90,26 +90,48 @@ load helpers
is "${#lines[@]}" "1" "setup check: no storage containers at start of test"
# Force a buildah timeout; this leaves a buildah container behind
+ local t0=$SECONDS
PODMAN_TIMEOUT=5 run_podman 124 build -t thiswillneverexist - <<EOF
FROM $IMAGE
+RUN touch /intermediate.image.to.be.pruned
RUN sleep 30
EOF
+ local t1=$SECONDS
+ local delta_t=$((t1 - t0))
+ if [[ $delta_t -gt 10 ]]; then
+ # FIXME FIXME FIXME: when buildah issue 3544 gets fixed and vendored,
+ # change 'echo' to 'die'
+ echo "podman build did not get killed within 10 seconds (actual time: $delta_t seconds)"
+ fi
run_podman ps -a
- is "${#lines[@]}" "1" "podman ps -a does not see buildah container"
+ is "${#lines[@]}" "1" "podman ps -a does not see buildah containers"
run_podman ps --external -a
- is "${#lines[@]}" "2" "podman ps -a --external sees buildah container"
+ is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers"
is "${lines[1]}" \
"[0-9a-f]\{12\} \+$IMAGE *buildah .* seconds ago .* storage .* ${PODMAN_TEST_IMAGE_NAME}-working-container" \
"podman ps --external"
- cid="${lines[1]:0:12}"
-
# 'rm -a' should be a NOP
run_podman rm -a
run_podman ps --external -a
- is "${#lines[@]}" "2" "podman ps -a --external sees buildah container"
+ is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers"
+
+ # Cannot prune intermediate image as it's being used by a buildah
+ # container.
+ run_podman image prune -f
+ is "$output" "" "No image is pruned"
+
+ # --external for removing buildah containers.
+ run_podman image prune -f --external
+ is "${#lines[@]}" "1" "Image used by build container is pruned"
+
+ # One buildah container has been removed.
+ run_podman ps --external -a
+ is "${#lines[@]}" "2" "podman ps -a --external sees buildah containers"
+
+ cid="${lines[1]:0:12}"
# We can't rm it without -f, but podman should issue a helpful message
run_podman 2 rm "$cid"
diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats
index 63a93e13b..ba37ea5e1 100644
--- a/test/system/060-mount.bats
+++ b/test/system/060-mount.bats
@@ -125,6 +125,7 @@ load helpers
run_podman exec $cid find /image-mount/etc/
# Clean up
+ run_podman stop -t 0 $cid
run_podman rm -f $cid
}
@@ -147,6 +148,7 @@ load helpers
run_podman inspect --format "{{(index .Mounts 0).RW}}" $cid
is "$output" "true" "inspect data includes image mount source"
+ run_podman stop -t 0 $cid
run_podman rm -f $cid
}
diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats
index 39f439e7b..38c38d671 100644
--- a/test/system/065-cp.bats
+++ b/test/system/065-cp.bats
@@ -256,6 +256,7 @@ load helpers
"
# From RUNNING container
+ local -a destcontainers=()
while read id src dest dest_fullname description; do
# dest may be "''" for empty table cells
if [[ $dest == "''" ]];then
@@ -265,26 +266,25 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman kill cpcontainer
- run_podman rm -f cpcontainer
+ run_podman kill cpcontainer ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
# From CREATED container
+ destcontainers=()
run_podman create --name cpcontainer --workdir=/srv $cpimage
while read id src dest dest_fullname description; do
# dest may be "''" for empty table cells
@@ -295,23 +295,21 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
-
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman rm -f cpcontainer
+ run_podman kill ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
run_podman rmi -f $cpimage
}
@@ -496,6 +494,7 @@ load helpers
"
# From RUNNING container
+ local -a destcontainers=()
while read src dest dest_fullname description; do
if [[ $src == "''" ]];then
unset src
@@ -510,28 +509,27 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman kill cpcontainer
- run_podman rm -f cpcontainer
+ run_podman kill cpcontainer ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
# From CREATED container
+ destcontainers=()
run_podman create --name cpcontainer --workdir=/srv $cpimage
while read src dest dest_fullname description; do
if [[ $src == "''" ]];then
@@ -547,26 +545,25 @@ ${randomcontent[1]}" "$description"
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman start $destcontainer
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman rm -f cpcontainer
+ run_podman kill ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
run_podman rmi -f $cpimage
}
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index 03c7984e2..4e89e299a 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -285,21 +285,11 @@ EOF
build_arg_implicit+="=$arg_implicit_value"
fi
- # FIXME FIXME FIXME: 2021-03-15: workaround for #9567 (slow ubuntu 2004):
- # we're seeing lots of timeouts in CI. Until/unless #9567 gets fixed,
- # let's get CI passing by extending the timeout when remote on ubuntu
- local localtimeout=${PODMAN_TIMEOUT}
- if is_remote; then
- if grep -qi ubuntu /etc/os-release; then
- localtimeout=$(( 2 * $localtimeout ))
- fi
- fi
-
# cd to the dir, so we test relative paths (important for podman-remote)
cd $PODMAN_TMPDIR
export arg_explicit="THIS SHOULD BE OVERRIDDEN BY COMMAND LINE!"
export arg_implicit=${arg_implicit_value}
- PODMAN_TIMEOUT=$localtimeout run_podman ${MOUNTS_CONF} build \
+ run_podman ${MOUNTS_CONF} build \
--build-arg arg_explicit=${arg_explicit_value} \
$build_arg_implicit \
--dns-search $nosuchdomain \
@@ -456,16 +446,24 @@ Labels.$label_name | $label_value
@test "podman build - COPY with ignore" {
local tmpdir=$PODMAN_TMPDIR/build-test-$(random_string 10)
- mkdir -p $tmpdir/subdir
+ mkdir -p $tmpdir/subdir{1,2}
# Create a bunch of files. Declare this as an array to avoid duplication
# because we iterate over that list below, checking for each file.
# A leading "-" indicates that the file SHOULD NOT exist in the built image
+ #
+ # Weird side effect of Buildah 3486, relating to subdirectories and
+ # wildcard patterns. See that PR for details, it's way too confusing
+ # to explain in a comment.
local -a files=(
-test1 -test1.txt
test2 test2.txt
- -subdir/sub1 -subdir/sub1.txt
- -subdir/sub2 -subdir/sub2.txt
+ subdir1/sub1 subdir1/sub1.txt
+ -subdir1/sub2 -subdir1/sub2.txt
+ subdir1/sub3 subdir1/sub3.txt
+ -subdir2/sub1 -subdir2/sub1.txt
+ -subdir2/sub2 -subdir2/sub2.txt
+ -subdir2/sub3 -subdir2/sub3.txt
this-file-does-not-match-anything-in-ignore-file
comment
)
@@ -492,8 +490,10 @@ EOF
# comment
test*
!test2*
-subdir
+subdir1
+subdir2
!*/sub1*
+!subdir1/sub3*
EOF
# Build an image. For .dockerignore
@@ -956,6 +956,15 @@ EOF
run_podman build -t build_test $tmpdir
}
+@test "podman build build context is a symlink to a directory" {
+ tmpdir=$PODMAN_TMPDIR/build-test
+ mkdir -p $tmpdir/target
+ ln -s target $tmpdir/link
+ echo FROM $IMAGE > $tmpdir/link/Dockerfile
+ echo RUN echo hello >> $tmpdir/link/Dockerfile
+ run_podman build -t build_test $tmpdir/link
+}
+
function teardown() {
# A timeout or other error in 'build' can leave behind stale images
# that podman can't even see and which will cascade into subsequent
diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats
index 1eb47dcfb..2314324a9 100644
--- a/test/system/080-pause.bats
+++ b/test/system/080-pause.bats
@@ -48,6 +48,7 @@ load helpers
# would imply that the container never paused.
is "$max_delta" "[3456]" "delta t between paused and restarted"
+ run_podman stop -t 0 $cname
run_podman rm -f $cname
# Pause/unpause on nonexistent name or id - these should all fail
@@ -73,6 +74,7 @@ load helpers
is "$output" "$cid" "podman unpause output"
run_podman ps --format '{{.ID}} {{.Names}} {{.Status}}'
is "$output" "${cid:0:12} $cname Up.*" "podman ps on resumed container"
+ run_podman stop -t 0 $cname
run_podman rm -f $cname
run_podman rm -f notrunning
}
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 97ea0f528..8be9ed5c5 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -32,7 +32,7 @@ verify_iid_and_name() {
echo "I am an invalid file and should cause a podman-load error" > $invalid
run_podman 125 load -i $invalid
# podman and podman-remote emit different messages; this is a common string
- is "$output" ".*payload does not match any of the supported image formats .*" \
+ is "$output" ".*payload does not match any of the supported image formats:.*" \
"load -i INVALID fails with expected diagnostic"
}
@@ -129,7 +129,7 @@ verify_iid_and_name() {
@test "podman load - redirect corrupt payload" {
run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!"
is "$output" \
- ".*payload does not match any of the supported image formats .*" \
+ ".*payload does not match any of the supported image formats:.*" \
"Diagnostic from 'podman load' unknown/corrupt payload"
}
@@ -183,4 +183,16 @@ verify_iid_and_name() {
run_podman rmi -f $img1 $img2
}
+@test "podman save --oci-accept-uncompressed-layers" {
+ archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar
+ untar=$PODMAN_TMPDIR/myuntar-$(random_string 8)
+ mkdir -p $untar
+
+ # Create a tarball, unpack it and make sure the layers are uncompressed.
+ run_podman save -o $archive --format oci-archive --uncompressed $IMAGE
+ run tar -C $untar -xvf $archive
+ run file $untar/blobs/sha256/*
+ is "$output" ".*POSIX tar archive" "layers are uncompressed"
+}
+
# vim: filetype=sh
diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats
index f6dc3f0af..e21be9ea4 100644
--- a/test/system/160-volumes.bats
+++ b/test/system/160-volumes.bats
@@ -21,8 +21,6 @@ function teardown() {
# Simple volume tests: share files between host and container
@test "podman run --volumes : basic" {
- skip_if_remote "volumes cannot be shared across hosts"
-
run_podman volume list --noheading
is "$output" "" "baseline: empty results from list --noheading"
@@ -192,9 +190,12 @@ EOF
run_podman volume create my_vol
run_podman run --rm -v my_vol:/data $IMAGE sh -c "echo hello >> /data/test"
run_podman volume create my_vol2
- run_podman volume export my_vol --output=hello.tar
+
+ tarfile=hello$(random_string | tr A-Z a-z).tar
+ run_podman volume export my_vol --output=$tarfile
# we want to use `run_podman volume export my_vol` but run_podman is wrapping EOF
- cat hello.tar | run_podman volume import my_vol2 -
+ run_podman volume import my_vol2 - < $tarfile
+ rm -f $tarfile
run_podman run --rm -v my_vol2:/data $IMAGE sh -c "cat /data/test"
is "$output" "hello" "output from second container"
run_podman volume rm my_vol
diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats
index e416629e6..28fe8eb92 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -12,13 +12,13 @@ function _check_health {
local testname="$1"
local tests="$2"
- run_podman inspect --format json healthcheck_c
+ run_podman inspect --format "{{json .State.Healthcheck}}" healthcheck_c
parse_table "$tests" | while read field expect;do
# (kludge to deal with parse_table and empty strings)
if [ "$expect" = "''" ]; then expect=""; fi
- actual=$(jq -r ".[0].State.Healthcheck.$field" <<<"$output")
+ actual=$(jq -r ".$field" <<<"$output")
is "$actual" "$expect" "$testname - .State.Healthcheck.$field"
done
}
@@ -108,6 +108,7 @@ Log[-1].Output |
is "$output" "unhealthy" "output from 'podman healthcheck run'"
# Clean up
+ run_podman stop -t 0 healthcheck_c
run_podman rm -f healthcheck_c
run_podman rmi healthcheck_i
}
diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats
index 031ba161b..dd439d3ae 100644
--- a/test/system/270-socket-activation.bats
+++ b/test/system/270-socket-activation.bats
@@ -69,26 +69,36 @@ function teardown() {
@test "podman system service - socket activation - no container" {
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
}
-@test "podman system service - socket activation - exist container " {
- run_podman run $IMAGE sleep 90
+@test "podman system service - socket activation - existing container" {
+ run_podman run -d $IMAGE sleep 90
+ cid="$output"
+
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
+
+ run_podman stop -t 0 $cid
+ run_podman rm -f $cid
}
-@test "podman system service - socket activation - kill rootless pause " {
+@test "podman system service - socket activation - kill rootless pause" {
if ! is_rootless; then
skip "root podman no need pause process"
fi
- run_podman run $IMAGE sleep 90
+ run_podman run -d $IMAGE sleep 90
+ cid="$output"
+
local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
if [ -f $pause_pid ]; then
kill -9 $(cat $pause_pid) 2> /dev/null
fi
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
+
+ run_podman stop -t 0 $cid
+ run_podman rm -f $cid
}
# vim: filetype=sh
diff --git a/test/system/330-corrupt-images.bats b/test/system/330-corrupt-images.bats
index eeffff3ec..86da06cb0 100644
--- a/test/system/330-corrupt-images.bats
+++ b/test/system/330-corrupt-images.bats
@@ -78,7 +78,7 @@ function _corrupt_image_test() {
# Run the requested command. Confirm it succeeds, with suitable warnings
run_podman $*
- is "$output" ".*error determining parent of image.*ignoring the error" \
+ is "$output" ".*Failed to determine parent of image.*ignoring the error" \
"$* with missing $what_to_rm"
run_podman images -a --noheading
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index 5ee0e0715..0f7c35c65 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -113,6 +113,10 @@ function check_label() {
@test "podman selinux: shared context in (some) namespaces" {
skip_if_no_selinux
+ # rootless users have no usable cgroups with cgroupsv1, so containers
+ # must use a pid namespace and not join an existing one.
+ skip_if_rootless_cgroupsv1
+
run_podman run -d --name myctr $IMAGE top
run_podman exec myctr cat -v /proc/self/attr/current
context_c1="$output"
diff --git a/test/system/420-cgroups.bats b/test/system/420-cgroups.bats
index 89c81a742..025a20012 100644
--- a/test/system/420-cgroups.bats
+++ b/test/system/420-cgroups.bats
@@ -8,9 +8,7 @@ load helpers
@test "podman run, preserves initial --cgroup-manager" {
skip_if_remote "podman-remote does not support --cgroup-manager"
- if is_rootless && is_cgroupsv1; then
- skip "not supported as rootless under cgroups v1"
- fi
+ skip_if_rootless_cgroupsv1
# Find out our default cgroup manager, and from that, get the non-default
run_podman info --format '{{.Host.CgroupManager}}'
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index ef00d0366..548f2d764 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -415,6 +415,10 @@ load helpers
run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
mac="$output"
+ # check network alias for container short id
+ run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").Aliases}}"
+ is "$output" "\[${cid:0:12}\]" "short container id in network aliases"
+
run_podman network disconnect $netname $cid
# check that we cannot curl (timeout after 3 sec)
@@ -443,6 +447,10 @@ load helpers
# connect a second network
run_podman network connect $netname2 $cid
+ # check network2 alias for container short id
+ run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname2\").Aliases}}"
+ is "$output" "\[${cid:0:12}\]" "short container id in network aliases"
+
# curl should work
run curl --max-time 3 -s $SERVER/index.txt
is "$output" "$random_1" "curl 127.0.0.1:/index.txt should work"
diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats
index fbb0da231..5f4610e9e 100644
--- a/test/system/600-completion.bats
+++ b/test/system/600-completion.bats
@@ -110,12 +110,10 @@ function check_shell_completion() {
is "$output" ".*localhost/$random_image_name:$random_image_tag${nl}" \
"$* $cmd: actual image listed in suggestions"
- # check that we complete the image with and without tag after at least one char is typed
+ # check that we complete the image with tag after at least one char is typed
run_completion "$@" $cmd "${extra_args[@]}" "${random_image_name:0:1}"
is "$output" ".*$random_image_name:$random_image_tag${nl}" \
"$* $cmd: image name:tag included in suggestions"
- is "$output" ".*$random_image_name${nl}" \
- "$* $cmd: image name(w/o tag) included in suggestions"
# check that we complete the image id after at least two chars are typed
run_completion "$@" $cmd "${extra_args[@]}" "${random_image_id:0:2}"
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 2b05cdd84..0785bffdf 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -69,11 +69,15 @@ RELABEL="system_u:object_r:container_file_t:s0"
TESTDIR=$PODMAN_TMPDIR/testdir
mkdir -p $TESTDIR
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
+
run_podman play kube - < $PODMAN_TMPDIR/test.yaml
if [ -e /usr/sbin/selinuxenabled -a /usr/sbin/selinuxenabled ]; then
run ls -Zd $TESTDIR
is "$output" ${RELABEL} "selinux relabel should have happened"
fi
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -86,6 +90,9 @@ RELABEL="system_u:object_r:container_file_t:s0"
run ls -Zd $TESTDIR
is "$output" ${RELABEL} "selinux relabel should have happened"
fi
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -102,12 +109,19 @@ RELABEL="system_u:object_r:container_file_t:s0"
infraID="$output"
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "slirp4netns" "network mode slirp4netns is set for the container"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
+
run_podman play kube --network none $PODMAN_TMPDIR/test.yaml
run_podman pod inspect --format {{.InfraContainerID}} "${lines[1]}"
infraID="$output"
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "none" "network mode none is set for the container"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -149,6 +163,9 @@ _EOF
run_podman play kube --start=false $PODMAN_TMPDIR/test.yaml
run_podman inspect --format "{{ .Config.User }}" test_pod-test
is "$output" bin "expect container within pod to run as the bin user"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
run_podman rmi -f userimage:latest
}
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 28ea924bb..666735b0c 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -428,6 +428,18 @@ function skip_if_cgroupsv1() {
fi
}
+######################
+# skip_if_rootless_cgroupsv1 # ...with an optional message
+######################
+function skip_if_rootless_cgroupsv1() {
+ if is_rootless; then
+ if ! is_cgroupsv2; then
+ local msg=$(_add_label_if_missing "$1" "rootless cgroupvs1")
+ skip "${msg:-not supported as rootless under cgroupsv1}"
+ fi
+ fi
+}
+
##################################
# skip_if_journald_unavailable # rhbz#1895105: rootless journald permissions
##################################
diff --git a/test/testvol/main.go b/test/testvol/main.go
index 721f47bcd..a0f58348b 100644
--- a/test/testvol/main.go
+++ b/test/testvol/main.go
@@ -59,7 +59,7 @@ func before(cmd *cobra.Command, args []string) error {
func main() {
if err := rootCmd.Execute(); err != nil {
- logrus.Errorf("Error running volume plugin: %v", err)
+ logrus.Errorf("Running volume plugin: %v", err)
os.Exit(1)
}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 80af7fb7c..bfefc58ec 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -19,7 +19,7 @@ import (
)
var (
- defaultWaitTimeout = 90
+ DefaultWaitTimeout = 90
OSReleasePath = "/etc/os-release"
ProcessOneCgroupPath = "/proc/1/cgroup"
)
@@ -317,15 +317,20 @@ func (s *PodmanSession) IsJSONOutputValid() bool {
return true
}
-// WaitWithDefaultTimeout waits for process finished with defaultWaitTimeout
+// WaitWithDefaultTimeout waits for process finished with DefaultWaitTimeout
func (s *PodmanSession) WaitWithDefaultTimeout() {
- Eventually(s, defaultWaitTimeout).Should(Exit())
+ s.WaitWithTimeout(DefaultWaitTimeout)
+}
+
+// WaitWithTimeout waits for process finished with DefaultWaitTimeout
+func (s *PodmanSession) WaitWithTimeout(timeout int) {
+ Eventually(s, timeout).Should(Exit())
os.Stdout.Sync()
os.Stderr.Sync()
fmt.Println("output:", s.OutputToString())
}
-// CreateTempDirinTempDir create a temp dir with prefix podman_test
+// CreateTempDirInTempDir create a temp dir with prefix podman_test
func CreateTempDirInTempDir() (string, error) {
return ioutil.TempDir("", "podman_test")
}
@@ -337,7 +342,7 @@ func SystemExec(command string, args []string) *PodmanSession {
if err != nil {
Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
}
- session.Wait(defaultWaitTimeout)
+ session.Wait(DefaultWaitTimeout)
return &PodmanSession{session}
}
diff --git a/test/version/main.go b/test/version/main.go
new file mode 100644
index 000000000..2a751de78
--- /dev/null
+++ b/test/version/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+ "fmt"
+
+ "github.com/containers/podman/v3/version"
+)
+
+func main() {
+ fmt.Printf(version.Version.String())
+}
diff --git a/utils/utils.go b/utils/utils.go
index 185ac4865..b08630d2f 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -12,6 +12,7 @@ import (
"sync"
"github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -190,7 +191,11 @@ func moveProcessToScope(pidPath, slice, scope string) error {
func MovePauseProcessToScope(pausePidPath string) {
err := moveProcessToScope(pausePidPath, "user.slice", "podman-pause.scope")
if err != nil {
- if RunsOnSystemd() {
+ unified, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ logrus.Warnf("Failed to detect if running with cgroup unified: %v", err)
+ }
+ if RunsOnSystemd() && unified {
logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err)
} else {
logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err)
diff --git a/utils/utils_supported.go b/utils/utils_supported.go
index ebc870d26..1404e3194 100644
--- a/utils/utils_supported.go
+++ b/utils/utils_supported.go
@@ -47,10 +47,10 @@ func RunUnderSystemdScope(pid int, slice string, unitName string) error {
// On errors check if the cgroup already exists, if it does move the process there
if props, err := conn.GetUnitTypeProperties(unitName, "Scope"); err == nil {
if cgroup, ok := props["ControlGroup"].(string); ok && cgroup != "" {
- if err := moveUnderCgroup(cgroup, "", []uint32{uint32(pid)}); err != nil {
- return err
+ if err := moveUnderCgroup(cgroup, "", []uint32{uint32(pid)}); err == nil {
+ return nil
}
- return nil
+ // On errors return the original error message we got from StartTransientUnit.
}
}
return err
diff --git a/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go b/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
index 1c74903ad..7c59ed23f 100644
--- a/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
+++ b/vendor/github.com/checkpoint-restore/checkpointctl/lib/metadata.go
@@ -6,12 +6,10 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
- "net"
"os"
"path/filepath"
"time"
- cnitypes "github.com/containernetworking/cni/pkg/types/current"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@@ -91,16 +89,73 @@ type CheckpointedPodOptions struct {
ProcessLabel string `json:"processLabel"`
}
-func DetectCheckpointArchiveType(checkpointDirectory string) (CheckpointType, error) {
- _, err := os.Stat(filepath.Join(checkpointDirectory, CheckpointedPodsFile))
+// This is metadata stored inside of Pod checkpoint archive
+type PodSandboxConfig struct {
+ Metadata SandboxMetadta `json:"metadata"`
+ Hostname string `json:"hostname"`
+}
+
+type SandboxMetadta struct {
+ Name string `json:"name"`
+ UID string `json:"uid"`
+ Namespace string `json:"namespace"`
+}
+
+func checkForFile(checkpointDirectory, file string) (bool, error) {
+ _, err := os.Stat(filepath.Join(checkpointDirectory, file))
if err != nil && !os.IsNotExist(err) {
- return Unknown, errors.Wrapf(err, "Failed to access %q\n", CheckpointedPodsFile)
+ return false, errors.Wrapf(err, "Failed to access %q\n", file)
+ }
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+
+ return true, nil
+}
+
+func DetectCheckpointArchiveType(checkpointDirectory string) (CheckpointType, error) {
+ kubelet, err := checkForFile(checkpointDirectory, CheckpointedPodsFile)
+ if os.IsNotExist(err) {
+ return Unknown, err
+ }
+
+ container, err := checkForFile(checkpointDirectory, ConfigDumpFile)
+ if os.IsNotExist(err) {
+ return Unknown, err
}
+
+ pod, err := checkForFile(checkpointDirectory, PodDumpFile)
if os.IsNotExist(err) {
+ return Unknown, err
+ }
+
+ if pod && !container && !kubelet {
+ return Pod, nil
+ }
+
+ if !pod && container && !kubelet {
return Container, nil
}
- return Kubelet, nil
+ if !pod && !container && kubelet {
+ return Kubelet, nil
+ }
+
+ return Unknown, nil
+}
+
+func ReadPodCheckpointDumpFile(checkpointDirectory string) (*PodSandboxConfig, string, error) {
+ var podSandboxConfig PodSandboxConfig
+ podDumpFile, err := ReadJSONFile(&podSandboxConfig, checkpointDirectory, PodDumpFile)
+
+ return &podSandboxConfig, podDumpFile, err
+}
+
+func ReadPodCheckpointOptionsFile(checkpointDirectory string) (*CheckpointedPodOptions, string, error) {
+ var checkpointedPodOptions CheckpointedPodOptions
+ podOptionsFile, err := ReadJSONFile(&checkpointedPodOptions, checkpointDirectory, PodOptionsFile)
+
+ return &checkpointedPodOptions, podOptionsFile, err
}
func ReadContainerCheckpointSpecDump(checkpointDirectory string) (*spec.Spec, string, error) {
@@ -124,13 +179,6 @@ func ReadContainerCheckpointDeletedFiles(checkpointDirectory string) ([]string,
return deletedFiles, deletedFilesFile, err
}
-func ReadContainerCheckpointNetworkStatus(checkpointDirectory string) ([]*cnitypes.Result, string, error) {
- var networkStatus []*cnitypes.Result
- networkStatusFile, err := ReadJSONFile(&networkStatus, checkpointDirectory, NetworkStatusFile)
-
- return networkStatus, networkStatusFile, err
-}
-
func ReadKubeletCheckpoints(checkpointsDirectory string) (*CheckpointMetadata, string, error) {
var checkpointMetadata CheckpointMetadata
checkpointMetadataPath, err := ReadJSONFile(&checkpointMetadata, checkpointsDirectory, CheckpointedPodsFile)
@@ -138,40 +186,6 @@ func ReadKubeletCheckpoints(checkpointsDirectory string) (*CheckpointMetadata, s
return &checkpointMetadata, checkpointMetadataPath, err
}
-func GetIPFromNetworkStatus(networkStatus []*cnitypes.Result) net.IP {
- if len(networkStatus) == 0 {
- return nil
- }
- // Take the first IP address
- if len(networkStatus[0].IPs) == 0 {
- return nil
- }
- IP := networkStatus[0].IPs[0].Address.IP
-
- return IP
-}
-
-func GetMACFromNetworkStatus(networkStatus []*cnitypes.Result) net.HardwareAddr {
- if len(networkStatus) == 0 {
- return nil
- }
- // Take the first device with a defined sandbox
- if len(networkStatus[0].Interfaces) == 0 {
- return nil
- }
- var MAC net.HardwareAddr
- MAC = nil
- for _, n := range networkStatus[0].Interfaces {
- if n.Sandbox != "" {
- MAC, _ = net.ParseMAC(n.Mac)
-
- break
- }
- }
-
- return MAC
-}
-
// WriteJSONFile marshalls and writes the given data to a JSON file
func WriteJSONFile(v interface{}, dir, file string) (string, error) {
fileJSON, err := json.MarshalIndent(v, "", " ")
diff --git a/vendor/github.com/containernetworking/cni/libcni/api.go b/vendor/github.com/containernetworking/cni/libcni/api.go
index 7e52bd838..0d82a2dd3 100644
--- a/vendor/github.com/containernetworking/cni/libcni/api.go
+++ b/vendor/github.com/containernetworking/cni/libcni/api.go
@@ -14,6 +14,12 @@
package libcni
+// Note this is the actual implementation of the CNI specification, which
+// is reflected in the https://github.com/containernetworking/cni/blob/master/SPEC.md file
+// it is typically bundled into runtime providers (i.e. containerd or cri-o would use this
+// before calling runc or hcsshim). It is also bundled into CNI providers as well, for example,
+// to add an IP to a container, to parse the configuration of the CNI and so on.
+
import (
"context"
"encoding/json"
@@ -25,6 +31,7 @@ import (
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/create"
"github.com/containernetworking/cni/pkg/utils"
"github.com/containernetworking/cni/pkg/version"
)
@@ -278,7 +285,7 @@ func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *R
unmarshaled := cachedInfo{}
if err := json.Unmarshal(bytes, &unmarshaled); err != nil {
- return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %v", netName, err)
+ return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %w", netName, err)
}
if unmarshaled.Kind != CNICacheV1 {
return nil, nil, fmt.Errorf("read cached network %q config has wrong kind: %v", netName, unmarshaled.Kind)
@@ -304,15 +311,8 @@ func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *Runtim
return nil, nil
}
- // Read the version of the cached result
- decoder := version.ConfigDecoder{}
- resultCniVersion, err := decoder.Decode(data)
- if err != nil {
- return nil, err
- }
-
- // Ensure we can understand the result
- result, err := version.NewResult(resultCniVersion, data)
+ // Load the cached result
+ result, err := create.CreateFromBytes(data)
if err != nil {
return nil, err
}
@@ -322,10 +322,10 @@ func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *Runtim
// should match the config version unless the config was changed
// while the container was running.
result, err = result.GetAsVersion(cniVersion)
- if err != nil && resultCniVersion != cniVersion {
- return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert cached result to config version %q: %w", cniVersion, err)
}
- return result, err
+ return result, nil
}
func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
@@ -346,18 +346,11 @@ func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf)
newBytes, err := json.Marshal(&cachedInfo.RawResult)
if err != nil {
- return nil, fmt.Errorf("failed to marshal cached network %q config: %v", netName, err)
+ return nil, fmt.Errorf("failed to marshal cached network %q config: %w", netName, err)
}
- // Read the version of the cached result
- decoder := version.ConfigDecoder{}
- resultCniVersion, err := decoder.Decode(newBytes)
- if err != nil {
- return nil, err
- }
-
- // Ensure we can understand the result
- result, err := version.NewResult(resultCniVersion, newBytes)
+ // Load the cached result
+ result, err := create.CreateFromBytes(newBytes)
if err != nil {
return nil, err
}
@@ -367,10 +360,10 @@ func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf)
// should match the config version unless the config was changed
// while the container was running.
result, err = result.GetAsVersion(cniVersion)
- if err != nil && resultCniVersion != cniVersion {
- return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
+ if err != nil {
+ return nil, fmt.Errorf("failed to convert cached result to config version %q: %w", cniVersion, err)
}
- return result, err
+ return result, nil
}
// GetNetworkListCachedResult returns the cached Result of the previous
@@ -428,12 +421,12 @@ func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList,
for _, net := range list.Plugins {
result, err = c.addNetwork(ctx, list.Name, list.CNIVersion, net, result, rt)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("plugin %s failed (add): %w", pluginDescription(net.Network), err)
}
}
if err = c.cacheAdd(result, list.Bytes, list.Name, rt); err != nil {
- return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
+ return nil, fmt.Errorf("failed to set network %q cached result: %w", list.Name, err)
}
return result, nil
@@ -469,7 +462,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis
cachedResult, err := c.getCachedResult(list.Name, list.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", list.Name, err)
}
for _, net := range list.Plugins {
@@ -506,14 +499,14 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
} else if gtet {
cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", list.Name, err)
}
}
for i := len(list.Plugins) - 1; i >= 0; i-- {
net := list.Plugins[i]
if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
- return err
+ return fmt.Errorf("plugin %s failed (delete): %w", pluginDescription(net.Network), err)
}
}
_ = c.cacheDel(list.Name, rt)
@@ -521,6 +514,19 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList,
return nil
}
+func pluginDescription(net *types.NetConf) string {
+ if net == nil {
+ return "<missing>"
+ }
+ pluginType := net.Type
+ out := fmt.Sprintf("type=%q", pluginType)
+ name := net.Name
+ if name != "" {
+ out += fmt.Sprintf(" name=%q", name)
+ }
+ return out
+}
+
// AddNetwork executes the plugin with the ADD command
func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt)
@@ -529,7 +535,7 @@ func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
}
if err = c.cacheAdd(result, net.Bytes, net.Network.Name, rt); err != nil {
- return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err)
+ return nil, fmt.Errorf("failed to set network %q cached result: %w", net.Network.Name, err)
}
return result, nil
@@ -546,7 +552,7 @@ func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *Ru
cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", net.Network.Name, err)
}
return c.checkNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt)
}
@@ -561,7 +567,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt
} else if gtet {
cachedResult, err = c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
if err != nil {
- return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
+ return fmt.Errorf("failed to get network %q cached result: %w", net.Network.Name, err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go
index d8920cf8c..d28135ff3 100644
--- a/vendor/github.com/containernetworking/cni/libcni/conf.go
+++ b/vendor/github.com/containernetworking/cni/libcni/conf.go
@@ -43,7 +43,7 @@ func (e NoConfigsFoundError) Error() string {
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
conf := &NetworkConfig{Bytes: bytes}
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
- return nil, fmt.Errorf("error parsing configuration: %s", err)
+ return nil, fmt.Errorf("error parsing configuration: %w", err)
}
if conf.Network.Type == "" {
return nil, fmt.Errorf("error parsing configuration: missing 'type'")
@@ -54,7 +54,7 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
func ConfFromFile(filename string) (*NetworkConfig, error) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
- return nil, fmt.Errorf("error reading %s: %s", filename, err)
+ return nil, fmt.Errorf("error reading %s: %w", filename, err)
}
return ConfFromBytes(bytes)
}
@@ -62,7 +62,7 @@ func ConfFromFile(filename string) (*NetworkConfig, error) {
func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
rawList := make(map[string]interface{})
if err := json.Unmarshal(bytes, &rawList); err != nil {
- return nil, fmt.Errorf("error parsing configuration list: %s", err)
+ return nil, fmt.Errorf("error parsing configuration list: %w", err)
}
rawName, ok := rawList["name"]
@@ -114,11 +114,11 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
for i, conf := range plugins {
newBytes, err := json.Marshal(conf)
if err != nil {
- return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err)
+ return nil, fmt.Errorf("failed to marshal plugin config %d: %w", i, err)
}
netConf, err := ConfFromBytes(newBytes)
if err != nil {
- return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err)
+ return nil, fmt.Errorf("failed to parse plugin config %d: %w", i, err)
}
list.Plugins = append(list.Plugins, netConf)
}
@@ -129,7 +129,7 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
func ConfListFromFile(filename string) (*NetworkConfigList, error) {
bytes, err := ioutil.ReadFile(filename)
if err != nil {
- return nil, fmt.Errorf("error reading %s: %s", filename, err)
+ return nil, fmt.Errorf("error reading %s: %w", filename, err)
}
return ConfListFromBytes(bytes)
}
@@ -218,7 +218,7 @@ func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*Net
config := make(map[string]interface{})
err := json.Unmarshal(original.Bytes, &config)
if err != nil {
- return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
+ return nil, fmt.Errorf("unmarshal existing network bytes: %w", err)
}
for key, value := range newValues {
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
index 8e6d30b82..e79bffe63 100644
--- a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
@@ -20,6 +20,7 @@ import (
"os"
"github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/create"
"github.com/containernetworking/cni/pkg/version"
)
@@ -83,14 +84,7 @@ func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte
return nil, err
}
- // Plugin must return result in same version as specified in netconf
- versionDecoder := &version.ConfigDecoder{}
- confVersion, err := versionDecoder.Decode(netconf)
- if err != nil {
- return nil, err
- }
-
- return version.NewResult(confVersion, stdoutBytes)
+ return create.CreateFromBytes(stdoutBytes)
}
func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error {
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
index 36f31678a..99b151ff2 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
@@ -22,25 +22,47 @@ import (
"os"
"github.com/containernetworking/cni/pkg/types"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
)
const ImplementedSpecVersion string = "0.2.0"
-var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
+var supportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ convert.RegisterConverter("0.1.0", []string{ImplementedSpecVersion}, convertFrom010)
+ convert.RegisterConverter(ImplementedSpecVersion, []string{"0.1.0"}, convertTo010)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
// Compatibility types for CNI version 0.1.0 and 0.2.0
+// NewResult creates a new Result object from JSON data. The JSON data
+// must be compatible with the CNI versions implemented by this type.
func NewResult(data []byte) (types.Result, error) {
result := &Result{}
if err := json.Unmarshal(data, result); err != nil {
return nil, err
}
- return result, nil
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ if result.CNIVersion == "" {
+ result.CNIVersion = "0.1.0"
+ }
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
}
+// GetResult converts the given Result object to the ImplementedSpecVersion
+// and returns the concrete type or an error
func GetResult(r types.Result) (*Result, error) {
- // We expect version 0.1.0/0.2.0 results
- result020, err := r.GetAsVersion(ImplementedSpecVersion)
+ result020, err := convert.Convert(r, ImplementedSpecVersion)
if err != nil {
return nil, err
}
@@ -51,6 +73,32 @@ func GetResult(r types.Result) (*Result, error) {
return result, nil
}
+func convertFrom010(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion != "0.2.0" {
+ panic("only converts to version 0.2.0")
+ }
+ fromResult := from.(*Result)
+ return &Result{
+ CNIVersion: ImplementedSpecVersion,
+ IP4: fromResult.IP4.Copy(),
+ IP6: fromResult.IP6.Copy(),
+ DNS: *fromResult.DNS.Copy(),
+ }, nil
+}
+
+func convertTo010(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion != "0.1.0" {
+ panic("only converts to version 0.1.0")
+ }
+ fromResult := from.(*Result)
+ return &Result{
+ CNIVersion: "0.1.0",
+ IP4: fromResult.IP4.Copy(),
+ IP6: fromResult.IP6.Copy(),
+ DNS: *fromResult.DNS.Copy(),
+ }, nil
+}
+
// Result is what gets returned from the plugin (via stdout) to the caller
type Result struct {
CNIVersion string `json:"cniVersion,omitempty"`
@@ -60,17 +108,16 @@ type Result struct {
}
func (r *Result) Version() string {
- return ImplementedSpecVersion
+ return r.CNIVersion
}
func (r *Result) GetAsVersion(version string) (types.Result, error) {
- for _, supportedVersion := range SupportedVersions {
- if version == supportedVersion {
- r.CNIVersion = version
- return r, nil
- }
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
}
- return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version)
+ return convert.Convert(r, version)
}
func (r *Result) Print() error {
@@ -93,6 +140,22 @@ type IPConfig struct {
Routes []types.Route
}
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ var routes []types.Route
+ for _, fromRoute := range i.Routes {
+ routes = append(routes, *fromRoute.Copy())
+ }
+ return &IPConfig{
+ IP: i.IP,
+ Gateway: i.Gateway,
+ Routes: routes,
+ }
+}
+
// net.IPNet is not JSON (un)marshallable so this duality is needed
// for our custom IPNet type
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/040/types.go b/vendor/github.com/containernetworking/cni/pkg/types/040/types.go
new file mode 100644
index 000000000..3633b0eaa
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/040/types.go
@@ -0,0 +1,306 @@
+// Copyright 2016 CNI 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 types040
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ types020 "github.com/containernetworking/cni/pkg/types/020"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+const ImplementedSpecVersion string = "0.4.0"
+
+var supportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ // Up-converters
+ convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.3.0", supportedVersions, convertInternal)
+ convert.RegisterConverter("0.3.1", supportedVersions, convertInternal)
+
+ // Down-converters
+ convert.RegisterConverter("0.4.0", []string{"0.3.0", "0.3.1"}, convertInternal)
+ convert.RegisterConverter("0.4.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+ convert.RegisterConverter("0.3.1", []string{"0.1.0", "0.2.0"}, convertTo02x)
+ convert.RegisterConverter("0.3.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := resultCurrent.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+func NewResultFromResult(result types.Result) (*Result, error) {
+ newResult, err := convert.Convert(result, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return newResult.(*Result), nil
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Interfaces []*Interface `json:"interfaces,omitempty"`
+ IPs []*IPConfig `json:"ips,omitempty"`
+ Routes []*types.Route `json:"routes,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+func convert020IPConfig(from *types020.IPConfig, ipVersion string) *IPConfig {
+ return &IPConfig{
+ Version: ipVersion,
+ Address: from.IP,
+ Gateway: from.Gateway,
+ }
+}
+
+func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*types020.Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ if fromResult.IP4 != nil {
+ toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP4, "4"))
+ for _, fromRoute := range fromResult.IP4.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ }
+
+ if fromResult.IP6 != nil {
+ toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP6, "6"))
+ for _, fromRoute := range fromResult.IP6.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ }
+
+ return toResult, nil
+}
+
+func convertInternal(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, fromIntf.Copy())
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, fromIPC.Copy())
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &types020.Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ }
+
+ for _, fromIP := range fromResult.IPs {
+ // Only convert the first IP address of each version as 0.2.0
+ // and earlier cannot handle multiple IP addresses
+ if fromIP.Version == "4" && toResult.IP4 == nil {
+ toResult.IP4 = &types020.IPConfig{
+ IP: fromIP.Address,
+ Gateway: fromIP.Gateway,
+ }
+ } else if fromIP.Version == "6" && toResult.IP6 == nil {
+ toResult.IP6 = &types020.IPConfig{
+ IP: fromIP.Address,
+ Gateway: fromIP.Gateway,
+ }
+ }
+ if toResult.IP4 != nil && toResult.IP6 != nil {
+ break
+ }
+ }
+
+ for _, fromRoute := range fromResult.Routes {
+ is4 := fromRoute.Dst.IP.To4() != nil
+ if is4 && toResult.IP4 != nil {
+ toResult.IP4.Routes = append(toResult.IP4.Routes, types.Route{
+ Dst: fromRoute.Dst,
+ GW: fromRoute.GW,
+ })
+ } else if !is4 && toResult.IP6 != nil {
+ toResult.IP6.Routes = append(toResult.IP6.Routes, types.Route{
+ Dst: fromRoute.Dst,
+ GW: fromRoute.GW,
+ })
+ }
+ }
+
+ // 0.2.0 and earlier require at least one IP address in the Result
+ if toResult.IP4 == nil && toResult.IP6 == nil {
+ return nil, fmt.Errorf("cannot convert: no valid IP addresses")
+ }
+
+ return toResult, nil
+}
+
+func (r *Result) Version() string {
+ return r.CNIVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
+ }
+ return convert.Convert(r, version)
+}
+
+func (r *Result) Print() error {
+ return r.PrintTo(os.Stdout)
+}
+
+func (r *Result) PrintTo(writer io.Writer) error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(data)
+ return err
+}
+
+// Interface contains values about the created interfaces
+type Interface struct {
+ Name string `json:"name"`
+ Mac string `json:"mac,omitempty"`
+ Sandbox string `json:"sandbox,omitempty"`
+}
+
+func (i *Interface) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *Interface) Copy() *Interface {
+ if i == nil {
+ return nil
+ }
+ newIntf := *i
+ return &newIntf
+}
+
+// Int returns a pointer to the int value passed in. Used to
+// set the IPConfig.Interface field.
+func Int(v int) *int {
+ return &v
+}
+
+// IPConfig contains values necessary to configure an IP address on an interface
+type IPConfig struct {
+ // IP version, either "4" or "6"
+ Version string
+ // Index into Result structs Interfaces list
+ Interface *int
+ Address net.IPNet
+ Gateway net.IP
+}
+
+func (i *IPConfig) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ ipc := &IPConfig{
+ Version: i.Version,
+ Address: i.Address,
+ Gateway: i.Gateway,
+ }
+ if i.Interface != nil {
+ intf := *i.Interface
+ ipc.Interface = &intf
+ }
+ return ipc
+}
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ Version string `json:"version"`
+ Interface *int `json:"interface,omitempty"`
+ Address types.IPNet `json:"address"`
+ Gateway net.IP `json:"gateway,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ Version: c.Version,
+ Interface: c.Interface,
+ Address: types.IPNet(c.Address),
+ Gateway: c.Gateway,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.Version = ipc.Version
+ c.Interface = ipc.Interface
+ c.Address = net.IPNet(ipc.Address)
+ c.Gateway = ipc.Gateway
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/100/types.go b/vendor/github.com/containernetworking/cni/pkg/types/100/types.go
new file mode 100644
index 000000000..0e1e8b857
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/100/types.go
@@ -0,0 +1,307 @@
+// Copyright 2016 CNI 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 types100
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ types040 "github.com/containernetworking/cni/pkg/types/040"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+const ImplementedSpecVersion string = "1.0.0"
+
+var supportedVersions = []string{ImplementedSpecVersion}
+
+// Register converters for all versions less than the implemented spec version
+func init() {
+ // Up-converters
+ convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
+ convert.RegisterConverter("0.3.0", supportedVersions, convertFrom04x)
+ convert.RegisterConverter("0.3.1", supportedVersions, convertFrom04x)
+ convert.RegisterConverter("0.4.0", supportedVersions, convertFrom04x)
+
+ // Down-converters
+ convert.RegisterConverter("1.0.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
+ convert.RegisterConverter("1.0.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
+
+ // Creator
+ convert.RegisterCreator(supportedVersions, NewResult)
+}
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ for _, v := range supportedVersions {
+ if result.CNIVersion == v {
+ return result, nil
+ }
+ }
+ return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
+ supportedVersions, result.CNIVersion)
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := resultCurrent.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+func NewResultFromResult(result types.Result) (*Result, error) {
+ newResult, err := convert.Convert(result, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return newResult.(*Result), nil
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Interfaces []*Interface `json:"interfaces,omitempty"`
+ IPs []*IPConfig `json:"ips,omitempty"`
+ Routes []*types.Route `json:"routes,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
+ result040, err := convert.Convert(from, "0.4.0")
+ if err != nil {
+ return nil, err
+ }
+ result100, err := convertFrom04x(result040, ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ return result100, nil
+}
+
+func convertIPConfigFrom040(from *types040.IPConfig) *IPConfig {
+ to := &IPConfig{
+ Address: from.Address,
+ Gateway: from.Gateway,
+ }
+ if from.Interface != nil {
+ intf := *from.Interface
+ to.Interface = &intf
+ }
+ return to
+}
+
+func convertInterfaceFrom040(from *types040.Interface) *Interface {
+ return &Interface{
+ Name: from.Name,
+ Mac: from.Mac,
+ Sandbox: from.Sandbox,
+ }
+}
+
+func convertFrom04x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*types040.Result)
+ toResult := &Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, convertInterfaceFrom040(fromIntf))
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, convertIPConfigFrom040(fromIPC))
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertIPConfigTo040(from *IPConfig) *types040.IPConfig {
+ version := "6"
+ if from.Address.IP.To4() != nil {
+ version = "4"
+ }
+ to := &types040.IPConfig{
+ Version: version,
+ Address: from.Address,
+ Gateway: from.Gateway,
+ }
+ if from.Interface != nil {
+ intf := *from.Interface
+ to.Interface = &intf
+ }
+ return to
+}
+
+func convertInterfaceTo040(from *Interface) *types040.Interface {
+ return &types040.Interface{
+ Name: from.Name,
+ Mac: from.Mac,
+ Sandbox: from.Sandbox,
+ }
+}
+
+func convertTo04x(from types.Result, toVersion string) (types.Result, error) {
+ fromResult := from.(*Result)
+ toResult := &types040.Result{
+ CNIVersion: toVersion,
+ DNS: *fromResult.DNS.Copy(),
+ Routes: []*types.Route{},
+ }
+ for _, fromIntf := range fromResult.Interfaces {
+ toResult.Interfaces = append(toResult.Interfaces, convertInterfaceTo040(fromIntf))
+ }
+ for _, fromIPC := range fromResult.IPs {
+ toResult.IPs = append(toResult.IPs, convertIPConfigTo040(fromIPC))
+ }
+ for _, fromRoute := range fromResult.Routes {
+ toResult.Routes = append(toResult.Routes, fromRoute.Copy())
+ }
+ return toResult, nil
+}
+
+func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
+ // First convert to 0.4.0
+ result040, err := convertTo04x(from, "0.4.0")
+ if err != nil {
+ return nil, err
+ }
+ result02x, err := convert.Convert(result040, toVersion)
+ if err != nil {
+ return nil, err
+ }
+ return result02x, nil
+}
+
+func (r *Result) Version() string {
+ return r.CNIVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ // If the creator of the result did not set the CNIVersion, assume it
+ // should be the highest spec version implemented by this Result
+ if r.CNIVersion == "" {
+ r.CNIVersion = ImplementedSpecVersion
+ }
+ return convert.Convert(r, version)
+}
+
+func (r *Result) Print() error {
+ return r.PrintTo(os.Stdout)
+}
+
+func (r *Result) PrintTo(writer io.Writer) error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = writer.Write(data)
+ return err
+}
+
+// Interface contains values about the created interfaces
+type Interface struct {
+ Name string `json:"name"`
+ Mac string `json:"mac,omitempty"`
+ Sandbox string `json:"sandbox,omitempty"`
+}
+
+func (i *Interface) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *Interface) Copy() *Interface {
+ if i == nil {
+ return nil
+ }
+ newIntf := *i
+ return &newIntf
+}
+
+// Int returns a pointer to the int value passed in. Used to
+// set the IPConfig.Interface field.
+func Int(v int) *int {
+ return &v
+}
+
+// IPConfig contains values necessary to configure an IP address on an interface
+type IPConfig struct {
+ // Index into Result structs Interfaces list
+ Interface *int
+ Address net.IPNet
+ Gateway net.IP
+}
+
+func (i *IPConfig) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+func (i *IPConfig) Copy() *IPConfig {
+ if i == nil {
+ return nil
+ }
+
+ ipc := &IPConfig{
+ Address: i.Address,
+ Gateway: i.Gateway,
+ }
+ if i.Interface != nil {
+ intf := *i.Interface
+ ipc.Interface = &intf
+ }
+ return ipc
+}
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ Interface *int `json:"interface,omitempty"`
+ Address types.IPNet `json:"address"`
+ Gateway net.IP `json:"gateway,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ Interface: c.Interface,
+ Address: types.IPNet(c.Address),
+ Gateway: c.Gateway,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.Interface = ipc.Interface
+ c.Address = net.IPNet(ipc.Address)
+ c.Gateway = ipc.Gateway
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go
index 4eac64899..7516f03ef 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/args.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/args.go
@@ -91,16 +91,26 @@ func LoadArgs(args string, container interface{}) error {
unknownArgs = append(unknownArgs, pair)
continue
}
- keyFieldIface := keyField.Addr().Interface()
- u, ok := keyFieldIface.(encoding.TextUnmarshaler)
+
+ var keyFieldInterface interface{}
+ switch {
+ case keyField.Kind() == reflect.Ptr:
+ keyField.Set(reflect.New(keyField.Type().Elem()))
+ keyFieldInterface = keyField.Interface()
+ case keyField.CanAddr() && keyField.Addr().CanInterface():
+ keyFieldInterface = keyField.Addr().Interface()
+ default:
+ return UnmarshalableArgsError{fmt.Errorf("field '%s' has no valid interface", keyString)}
+ }
+ u, ok := keyFieldInterface.(encoding.TextUnmarshaler)
if !ok {
return UnmarshalableArgsError{fmt.Errorf(
"ARGS: cannot unmarshal into field '%s' - type '%s' does not implement encoding.TextUnmarshaler",
- keyString, reflect.TypeOf(keyFieldIface))}
+ keyString, reflect.TypeOf(keyFieldInterface))}
}
err := u.UnmarshalText([]byte(valueString))
if err != nil {
- return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
+ return fmt.Errorf("ARGS: error parsing value of pair %q: %w", pair, err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/create/create.go b/vendor/github.com/containernetworking/cni/pkg/types/create/create.go
new file mode 100644
index 000000000..ed28b33e8
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/create/create.go
@@ -0,0 +1,56 @@
+// Copyright 2016 CNI 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 create
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+ convert "github.com/containernetworking/cni/pkg/types/internal"
+)
+
+// DecodeVersion returns the CNI version from CNI configuration or result JSON,
+// or an error if the operation could not be performed.
+func DecodeVersion(jsonBytes []byte) (string, error) {
+ var conf struct {
+ CNIVersion string `json:"cniVersion"`
+ }
+ err := json.Unmarshal(jsonBytes, &conf)
+ if err != nil {
+ return "", fmt.Errorf("decoding version from network config: %w", err)
+ }
+ if conf.CNIVersion == "" {
+ return "0.1.0", nil
+ }
+ return conf.CNIVersion, nil
+}
+
+// Create creates a CNI Result using the given JSON with the expected
+// version, or an error if the creation could not be performed
+func Create(version string, bytes []byte) (types.Result, error) {
+ return convert.Create(version, bytes)
+}
+
+// CreateFromBytes creates a CNI Result from the given JSON, automatically
+// detecting the CNI spec version of the result. An error is returned if the
+// operation could not be performed.
+func CreateFromBytes(bytes []byte) (types.Result, error) {
+ version, err := DecodeVersion(bytes)
+ if err != nil {
+ return nil, err
+ }
+ return convert.Create(version, bytes)
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
deleted file mode 100644
index 754cc6e72..000000000
--- a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2016 CNI 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 current
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "net"
- "os"
-
- "github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/020"
-)
-
-const ImplementedSpecVersion string = "0.4.0"
-
-var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
-
-func NewResult(data []byte) (types.Result, error) {
- result := &Result{}
- if err := json.Unmarshal(data, result); err != nil {
- return nil, err
- }
- return result, nil
-}
-
-func GetResult(r types.Result) (*Result, error) {
- resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
- if err != nil {
- return nil, err
- }
- result, ok := resultCurrent.(*Result)
- if !ok {
- return nil, fmt.Errorf("failed to convert result")
- }
- return result, nil
-}
-
-var resultConverters = []struct {
- versions []string
- convert func(types.Result) (*Result, error)
-}{
- {types020.SupportedVersions, convertFrom020},
- {SupportedVersions, convertFrom030},
-}
-
-func convertFrom020(result types.Result) (*Result, error) {
- oldResult, err := types020.GetResult(result)
- if err != nil {
- return nil, err
- }
-
- newResult := &Result{
- CNIVersion: ImplementedSpecVersion,
- DNS: oldResult.DNS,
- Routes: []*types.Route{},
- }
-
- if oldResult.IP4 != nil {
- newResult.IPs = append(newResult.IPs, &IPConfig{
- Version: "4",
- Address: oldResult.IP4.IP,
- Gateway: oldResult.IP4.Gateway,
- })
- for _, route := range oldResult.IP4.Routes {
- newResult.Routes = append(newResult.Routes, &types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- if oldResult.IP6 != nil {
- newResult.IPs = append(newResult.IPs, &IPConfig{
- Version: "6",
- Address: oldResult.IP6.IP,
- Gateway: oldResult.IP6.Gateway,
- })
- for _, route := range oldResult.IP6.Routes {
- newResult.Routes = append(newResult.Routes, &types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- return newResult, nil
-}
-
-func convertFrom030(result types.Result) (*Result, error) {
- newResult, ok := result.(*Result)
- if !ok {
- return nil, fmt.Errorf("failed to convert result")
- }
- newResult.CNIVersion = ImplementedSpecVersion
- return newResult, nil
-}
-
-func NewResultFromResult(result types.Result) (*Result, error) {
- version := result.Version()
- for _, converter := range resultConverters {
- for _, supportedVersion := range converter.versions {
- if version == supportedVersion {
- return converter.convert(result)
- }
- }
- }
- return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
-}
-
-// Result is what gets returned from the plugin (via stdout) to the caller
-type Result struct {
- CNIVersion string `json:"cniVersion,omitempty"`
- Interfaces []*Interface `json:"interfaces,omitempty"`
- IPs []*IPConfig `json:"ips,omitempty"`
- Routes []*types.Route `json:"routes,omitempty"`
- DNS types.DNS `json:"dns,omitempty"`
-}
-
-// Convert to the older 0.2.0 CNI spec Result type
-func (r *Result) convertTo020() (*types020.Result, error) {
- oldResult := &types020.Result{
- CNIVersion: types020.ImplementedSpecVersion,
- DNS: r.DNS,
- }
-
- for _, ip := range r.IPs {
- // Only convert the first IP address of each version as 0.2.0
- // and earlier cannot handle multiple IP addresses
- if ip.Version == "4" && oldResult.IP4 == nil {
- oldResult.IP4 = &types020.IPConfig{
- IP: ip.Address,
- Gateway: ip.Gateway,
- }
- } else if ip.Version == "6" && oldResult.IP6 == nil {
- oldResult.IP6 = &types020.IPConfig{
- IP: ip.Address,
- Gateway: ip.Gateway,
- }
- }
-
- if oldResult.IP4 != nil && oldResult.IP6 != nil {
- break
- }
- }
-
- for _, route := range r.Routes {
- is4 := route.Dst.IP.To4() != nil
- if is4 && oldResult.IP4 != nil {
- oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- } else if !is4 && oldResult.IP6 != nil {
- oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
- Dst: route.Dst,
- GW: route.GW,
- })
- }
- }
-
- if oldResult.IP4 == nil && oldResult.IP6 == nil {
- return nil, fmt.Errorf("cannot convert: no valid IP addresses")
- }
-
- return oldResult, nil
-}
-
-func (r *Result) Version() string {
- return ImplementedSpecVersion
-}
-
-func (r *Result) GetAsVersion(version string) (types.Result, error) {
- switch version {
- case "0.3.0", "0.3.1", ImplementedSpecVersion:
- r.CNIVersion = version
- return r, nil
- case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
- return r.convertTo020()
- }
- return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
-}
-
-func (r *Result) Print() error {
- return r.PrintTo(os.Stdout)
-}
-
-func (r *Result) PrintTo(writer io.Writer) error {
- data, err := json.MarshalIndent(r, "", " ")
- if err != nil {
- return err
- }
- _, err = writer.Write(data)
- return err
-}
-
-// Convert this old version result to the current CNI version result
-func (r *Result) Convert() (*Result, error) {
- return r, nil
-}
-
-// Interface contains values about the created interfaces
-type Interface struct {
- Name string `json:"name"`
- Mac string `json:"mac,omitempty"`
- Sandbox string `json:"sandbox,omitempty"`
-}
-
-func (i *Interface) String() string {
- return fmt.Sprintf("%+v", *i)
-}
-
-// Int returns a pointer to the int value passed in. Used to
-// set the IPConfig.Interface field.
-func Int(v int) *int {
- return &v
-}
-
-// IPConfig contains values necessary to configure an IP address on an interface
-type IPConfig struct {
- // IP version, either "4" or "6"
- Version string
- // Index into Result structs Interfaces list
- Interface *int
- Address net.IPNet
- Gateway net.IP
-}
-
-func (i *IPConfig) String() string {
- return fmt.Sprintf("%+v", *i)
-}
-
-// JSON (un)marshallable types
-type ipConfig struct {
- Version string `json:"version"`
- Interface *int `json:"interface,omitempty"`
- Address types.IPNet `json:"address"`
- Gateway net.IP `json:"gateway,omitempty"`
-}
-
-func (c *IPConfig) MarshalJSON() ([]byte, error) {
- ipc := ipConfig{
- Version: c.Version,
- Interface: c.Interface,
- Address: types.IPNet(c.Address),
- Gateway: c.Gateway,
- }
-
- return json.Marshal(ipc)
-}
-
-func (c *IPConfig) UnmarshalJSON(data []byte) error {
- ipc := ipConfig{}
- if err := json.Unmarshal(data, &ipc); err != nil {
- return err
- }
-
- c.Version = ipc.Version
- c.Interface = ipc.Interface
- c.Address = net.IPNet(ipc.Address)
- c.Gateway = ipc.Gateway
- return nil
-}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go b/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
new file mode 100644
index 000000000..bdbe4b0a5
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
@@ -0,0 +1,92 @@
+// Copyright 2016 CNI 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 convert
+
+import (
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+// ConvertFn should convert from the given arbitrary Result type into a
+// Result implementing CNI specification version passed in toVersion.
+// The function is guaranteed to be passed a Result type matching the
+// fromVersion it was registered with, and is guaranteed to be
+// passed a toVersion matching one of the toVersions it was registered with.
+type ConvertFn func(from types.Result, toVersion string) (types.Result, error)
+
+type converter struct {
+ // fromVersion is the CNI Result spec version that convertFn accepts
+ fromVersion string
+ // toVersions is a list of versions that convertFn can convert to
+ toVersions []string
+ convertFn ConvertFn
+}
+
+var converters []*converter
+
+func findConverter(fromVersion, toVersion string) *converter {
+ for _, c := range converters {
+ if c.fromVersion == fromVersion {
+ for _, v := range c.toVersions {
+ if v == toVersion {
+ return c
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Convert converts a CNI Result to the requested CNI specification version,
+// or returns an error if the conversion could not be performed or failed
+func Convert(from types.Result, toVersion string) (types.Result, error) {
+ if toVersion == "" {
+ toVersion = "0.1.0"
+ }
+
+ fromVersion := from.Version()
+
+ // Shortcut for same version
+ if fromVersion == toVersion {
+ return from, nil
+ }
+
+ // Otherwise find the right converter
+ c := findConverter(fromVersion, toVersion)
+ if c == nil {
+ return nil, fmt.Errorf("no converter for CNI result version %s to %s",
+ fromVersion, toVersion)
+ }
+ return c.convertFn(from, toVersion)
+}
+
+// RegisterConverter registers a CNI Result converter. SHOULD NOT BE CALLED
+// EXCEPT FROM CNI ITSELF.
+func RegisterConverter(fromVersion string, toVersions []string, convertFn ConvertFn) {
+ // Make sure there is no converter already registered for these
+ // from and to versions
+ for _, v := range toVersions {
+ if findConverter(fromVersion, v) != nil {
+ panic(fmt.Sprintf("converter already registered for %s to %s",
+ fromVersion, v))
+ }
+ }
+ converters = append(converters, &converter{
+ fromVersion: fromVersion,
+ toVersions: toVersions,
+ convertFn: convertFn,
+ })
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go b/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
new file mode 100644
index 000000000..963630912
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
@@ -0,0 +1,66 @@
+// Copyright 2016 CNI 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 convert
+
+import (
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+type ResultFactoryFunc func([]byte) (types.Result, error)
+
+type creator struct {
+ // CNI Result spec versions that createFn can create a Result for
+ versions []string
+ createFn ResultFactoryFunc
+}
+
+var creators []*creator
+
+func findCreator(version string) *creator {
+ for _, c := range creators {
+ for _, v := range c.versions {
+ if v == version {
+ return c
+ }
+ }
+ }
+ return nil
+}
+
+// Create creates a CNI Result using the given JSON, or an error if the creation
+// could not be performed
+func Create(version string, bytes []byte) (types.Result, error) {
+ if c := findCreator(version); c != nil {
+ return c.createFn(bytes)
+ }
+ return nil, fmt.Errorf("unsupported CNI result version %q", version)
+}
+
+// RegisterCreator registers a CNI Result creator. SHOULD NOT BE CALLED
+// EXCEPT FROM CNI ITSELF.
+func RegisterCreator(versions []string, createFn ResultFactoryFunc) {
+ // Make sure there is no creator already registered for these versions
+ for _, v := range versions {
+ if findCreator(v) != nil {
+ panic(fmt.Sprintf("creator already registered for %s", v))
+ }
+ }
+ creators = append(creators, &creator{
+ versions: versions,
+ createFn: createFn,
+ })
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go
index 3fa757a5d..fba17dfc0 100644
--- a/vendor/github.com/containernetworking/cni/pkg/types/types.go
+++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go
@@ -83,8 +83,6 @@ type NetConfList struct {
Plugins []*NetConf `json:"plugins,omitempty"`
}
-type ResultFactoryFunc func([]byte) (Result, error)
-
// Result is an interface that provides the result of plugin execution
type Result interface {
// The highest CNI specification result version the result supports
@@ -118,6 +116,24 @@ type DNS struct {
Options []string `json:"options,omitempty"`
}
+func (d *DNS) Copy() *DNS {
+ if d == nil {
+ return nil
+ }
+
+ to := &DNS{Domain: d.Domain}
+ for _, ns := range d.Nameservers {
+ to.Nameservers = append(to.Nameservers, ns)
+ }
+ for _, s := range d.Search {
+ to.Search = append(to.Search, s)
+ }
+ for _, o := range d.Options {
+ to.Options = append(to.Options, o)
+ }
+ return to
+}
+
type Route struct {
Dst net.IPNet
GW net.IP
@@ -127,6 +143,17 @@ func (r *Route) String() string {
return fmt.Sprintf("%+v", *r)
}
+func (r *Route) Copy() *Route {
+ if r == nil {
+ return nil
+ }
+
+ return &Route{
+ Dst: r.Dst,
+ GW: r.GW,
+ }
+}
+
// Well known error codes
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
const (
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/conf.go b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
index 3cca58bbe..808c33b83 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/conf.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
@@ -15,23 +15,12 @@
package version
import (
- "encoding/json"
- "fmt"
+ "github.com/containernetworking/cni/pkg/types/create"
)
// ConfigDecoder can decode the CNI version available in network config data
type ConfigDecoder struct{}
func (*ConfigDecoder) Decode(jsonBytes []byte) (string, error) {
- var conf struct {
- CNIVersion string `json:"cniVersion"`
- }
- err := json.Unmarshal(jsonBytes, &conf)
- if err != nil {
- return "", fmt.Errorf("decoding version from network config: %s", err)
- }
- if conf.CNIVersion == "" {
- return "0.1.0", nil
- }
- return conf.CNIVersion, nil
+ return create.DecodeVersion(jsonBytes)
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
index 1df427243..d4bc9d169 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
@@ -68,7 +68,7 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
var info pluginInfo
err := json.Unmarshal(jsonBytes, &info)
if err != nil {
- return nil, fmt.Errorf("decoding version info: %s", err)
+ return nil, fmt.Errorf("decoding version info: %w", err)
}
if info.CNIVersion_ == "" {
return nil, fmt.Errorf("decoding version info: missing field cniVersion")
@@ -97,20 +97,20 @@ func ParseVersion(version string) (int, int, int, error) {
major, err := strconv.Atoi(parts[0])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %w", parts[0], err)
}
if len(parts) >= 2 {
minor, err = strconv.Atoi(parts[1])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %w", parts[1], err)
}
}
if len(parts) >= 3 {
micro, err = strconv.Atoi(parts[2])
if err != nil {
- return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err)
+ return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %w", parts[2], err)
}
}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go
index 8f3508e61..1326f8038 100644
--- a/vendor/github.com/containernetworking/cni/pkg/version/version.go
+++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go
@@ -19,13 +19,13 @@ import (
"fmt"
"github.com/containernetworking/cni/pkg/types"
- "github.com/containernetworking/cni/pkg/types/020"
- "github.com/containernetworking/cni/pkg/types/current"
+ types100 "github.com/containernetworking/cni/pkg/types/100"
+ "github.com/containernetworking/cni/pkg/types/create"
)
// Current reports the version of the CNI spec implemented by this library
func Current() string {
- return "0.4.0"
+ return types100.ImplementedSpecVersion
}
// Legacy PluginInfo describes a plugin that is backwards compatible with the
@@ -36,29 +36,28 @@ func Current() string {
// Any future CNI spec versions which meet this definition should be added to
// this list.
var Legacy = PluginSupports("0.1.0", "0.2.0")
-var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0")
+var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0")
-var resultFactories = []struct {
- supportedVersions []string
- newResult types.ResultFactoryFunc
-}{
- {current.SupportedVersions, current.NewResult},
- {types020.SupportedVersions, types020.NewResult},
+// VersionsFrom returns a list of versions starting from min, inclusive
+func VersionsStartingFrom(min string) PluginInfo {
+ out := []string{}
+ // cheat, just assume ordered
+ ok := false
+ for _, v := range All.SupportedVersions() {
+ if !ok && v == min {
+ ok = true
+ }
+ if ok {
+ out = append(out, v)
+ }
+ }
+ return PluginSupports(out...)
}
// Finds a Result object matching the requested version (if any) and asks
// that object to parse the plugin result, returning an error if parsing failed.
func NewResult(version string, resultBytes []byte) (types.Result, error) {
- reconciler := &Reconciler{}
- for _, resultFactory := range resultFactories {
- err := reconciler.CheckRaw(version, resultFactory.supportedVersions)
- if err == nil {
- // Result supports this version
- return resultFactory.newResult(resultBytes)
- }
- }
-
- return nil, fmt.Errorf("unsupported CNI result version %q", version)
+ return create.Create(version, resultBytes)
}
// ParsePrevResult parses a prevResult in a NetConf structure and sets
@@ -68,15 +67,22 @@ func ParsePrevResult(conf *types.NetConf) error {
return nil
}
+ // Prior to 1.0.0, Result types may not marshal a CNIVersion. Since the
+ // result version must match the config version, if the Result's version
+ // is empty, inject the config version.
+ if ver, ok := conf.RawPrevResult["CNIVersion"]; !ok || ver == "" {
+ conf.RawPrevResult["CNIVersion"] = conf.CNIVersion
+ }
+
resultBytes, err := json.Marshal(conf.RawPrevResult)
if err != nil {
- return fmt.Errorf("could not serialize prevResult: %v", err)
+ return fmt.Errorf("could not serialize prevResult: %w", err)
}
conf.RawPrevResult = nil
- conf.PrevResult, err = NewResult(conf.CNIVersion, resultBytes)
+ conf.PrevResult, err = create.Create(conf.CNIVersion, resultBytes)
if err != nil {
- return fmt.Errorf("could not parse prevResult: %v", err)
+ return fmt.Errorf("could not parse prevResult: %w", err)
}
return nil
diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go
index a44f098ad..636b97bfd 100644
--- a/vendor/github.com/containers/common/libimage/copier.go
+++ b/vendor/github.com/containers/common/libimage/copier.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/retry"
"github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/signature"
storageTransport "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/types"
@@ -40,6 +41,10 @@ type CopyOptions struct {
// Allows for customizing the destination reference lookup. This can
// be used to use custom blob caches.
DestinationLookupReferenceFunc LookupReferenceFunc
+ // CompressionFormat is the format to use for the compression of the blobs
+ CompressionFormat *compression.Algorithm
+ // CompressionLevel specifies what compression level is used
+ CompressionLevel *int
// containers-auth.json(5) file to use when authenticating against
// container registries.
@@ -65,6 +70,8 @@ type CopyOptions struct {
// types. Short forms (e.g., oci, v2s2) used by some tools are not
// supported.
ManifestMIMEType string
+ // Accept uncompressed layers when copying OCI images.
+ OciAcceptUncompressedLayers bool
// If OciEncryptConfig is non-nil, it indicates that an image should be
// encrypted. The encryption options is derived from the construction
// of EncryptConfig object. Note: During initial encryption process of
@@ -242,6 +249,17 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) {
c.systemContext.DockerCertPath = options.CertDirPath
}
+ if options.CompressionFormat != nil {
+ c.systemContext.CompressionFormat = options.CompressionFormat
+ }
+
+ if options.CompressionLevel != nil {
+ c.systemContext.CompressionLevel = options.CompressionLevel
+ }
+
+ // NOTE: for the sake of consistency it's called Oci* in the CopyOptions.
+ c.systemContext.OCIAcceptUncompressedLayers = options.OciAcceptUncompressedLayers
+
policy, err := signature.DefaultPolicy(c.systemContext)
if err != nil {
return nil, err
@@ -286,7 +304,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) {
defaultContainerConfig, err := config.Default()
if err != nil {
- logrus.Warnf("failed to get container config for copy options: %v", err)
+ logrus.Warnf("Failed to get container config for copy options: %v", err)
} else {
c.imageCopyOptions.MaxParallelDownloads = defaultContainerConfig.Engine.ImageParallelCopies
}
diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go
index 0cc5cc311..833f940cc 100644
--- a/vendor/github.com/containers/common/libimage/filters.go
+++ b/vendor/github.com/containers/common/libimage/filters.go
@@ -47,11 +47,11 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) {
// compileImageFilters creates `filterFunc`s for the specified filters. The
// required format is `key=value` with the following supported keys:
// after, since, before, containers, dangling, id, label, readonly, reference, intermediate
-func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]filterFunc, error) {
- logrus.Tracef("Parsing image filters %s", filters)
+func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) {
+ logrus.Tracef("Parsing image filters %s", options.Filters)
filterFuncs := []filterFunc{}
- for _, filter := range filters {
+ for _, filter := range options.Filters {
var key, value string
split := strings.SplitN(filter, "=", 2)
if len(split) != 2 {
@@ -77,11 +77,16 @@ func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]
filterFuncs = append(filterFuncs, filterBefore(img.Created()))
case "containers":
- containers, err := strconv.ParseBool(value)
- if err != nil {
- return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value)
+ switch value {
+ case "false", "true":
+ case "external":
+ if options.IsExternalContainerFunc == nil {
+ return nil, fmt.Errorf("libimage error: external containers filter without callback")
+ }
+ default:
+ return nil, fmt.Errorf("unsupported value %q for containers filter", value)
}
- filterFuncs = append(filterFuncs, filterContainers(containers))
+ filterFuncs = append(filterFuncs, filterContainers(value, options.IsExternalContainerFunc))
case "dangling":
dangling, err := strconv.ParseBool(value)
@@ -190,13 +195,28 @@ func filterReadOnly(value bool) filterFunc {
}
// filterContainers creates a container filter for matching the specified value.
-func filterContainers(value bool) filterFunc {
+func filterContainers(value string, fn IsExternalContainerFunc) filterFunc {
return func(img *Image) (bool, error) {
ctrs, err := img.Containers()
if err != nil {
return false, err
}
- return (len(ctrs) > 0) == value, nil
+ if value != "external" {
+ boolValue := value == "true"
+ return (len(ctrs) > 0) == boolValue, nil
+ }
+
+ // Check whether all associated containers are external ones.
+ for _, c := range ctrs {
+ isExternal, err := fn(c)
+ if err != nil {
+ return false, fmt.Errorf("checking if %s is an external container in filter: %w", c, err)
+ }
+ if !isExternal {
+ return isExternal, nil
+ }
+ }
+ return true, nil
}
}
diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go
index ff7d546e9..00a2d620e 100644
--- a/vendor/github.com/containers/common/libimage/image.go
+++ b/vendor/github.com/containers/common/libimage/image.go
@@ -2,6 +2,7 @@ package libimage
import (
"context"
+ "fmt"
"path/filepath"
"sort"
"strings"
@@ -51,7 +52,7 @@ func (i *Image) reload() error {
logrus.Tracef("Reloading image %s", i.ID())
img, err := i.runtime.store.Image(i.ID())
if err != nil {
- return errors.Wrap(err, "error reloading image")
+ return errors.Wrap(err, "reloading image")
}
i.storageImage = img
i.cached.imageSource = nil
@@ -232,11 +233,15 @@ func (i *Image) Containers() ([]string, error) {
}
// removeContainers removes all containers using the image.
-func (i *Image) removeContainers(fn RemoveContainerFunc) error {
- // Execute the custom removal func if specified.
- if fn != nil {
+func (i *Image) removeContainers(options *RemoveImagesOptions) error {
+ if !options.Force && !options.ExternalContainers {
+ // Nothing to do.
+ return nil
+ }
+
+ if options.Force && options.RemoveContainerFunc != nil {
logrus.Debugf("Removing containers of image %s with custom removal function", i.ID())
- if err := fn(i.ID()); err != nil {
+ if err := options.RemoveContainerFunc(i.ID()); err != nil {
return err
}
}
@@ -246,6 +251,19 @@ func (i *Image) removeContainers(fn RemoveContainerFunc) error {
return err
}
+ if !options.Force && options.ExternalContainers {
+ // All containers must be external ones.
+ for _, cID := range containers {
+ isExternal, err := options.IsExternalContainerFunc(cID)
+ if err != nil {
+ return fmt.Errorf("checking if %s is an external container: %w", cID, err)
+ }
+ if !isExternal {
+ return fmt.Errorf("cannot remove container %s: not an external container", cID)
+ }
+ }
+ }
+
logrus.Debugf("Removing containers of image %s from the local containers storage", i.ID())
var multiE error
for _, cID := range containers {
@@ -392,11 +410,9 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
return processedIDs, nil
}
- // Perform the actual removal. First, remove containers if needed.
- if options.Force {
- if err := i.removeContainers(options.RemoveContainerFunc); err != nil {
- return processedIDs, err
- }
+ // Perform the container removal, if needed.
+ if err := i.removeContainers(options); err != nil {
+ return processedIDs, err
}
// Podman/Docker compat: we only report an image as removed if it has
@@ -406,7 +422,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err)
hasChildren = false
}
@@ -416,7 +432,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining parent of image: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine parent of image: %v, ignoring the error", err)
parent = nil
}
@@ -440,7 +456,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// See Podman commit fd9dd7065d44: we need to
// be tolerant toward corrupted images.
- logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err)
danglingParent = false
}
if !danglingParent {
@@ -462,7 +478,7 @@ func (i *Image) Tag(name string) error {
ref, err := NormalizeName(name)
if err != nil {
- return errors.Wrapf(err, "error normalizing name %q", name)
+ return errors.Wrapf(err, "normalizing name %q", name)
}
if _, isDigested := ref.(reference.Digested); isDigested {
@@ -499,7 +515,7 @@ func (i *Image) Untag(name string) error {
ref, err := NormalizeName(name)
if err != nil {
- return errors.Wrapf(err, "error normalizing name %q", name)
+ return errors.Wrapf(err, "normalizing name %q", name)
}
// FIXME: this is breaking Podman CI but must be re-enabled once
@@ -715,10 +731,18 @@ func (i *Image) Size() (int64, error) {
return i.runtime.store.ImageSize(i.ID())
}
+// HasDifferentDigestOptions allows for customizing the check if another
+// (remote) image has a different digest.
+type HasDifferentDigestOptions struct {
+ // containers-auth.json(5) file to use when authenticating against
+ // container registries.
+ AuthFilePath string
+}
+
// HasDifferentDigest returns true if the image specified by `remoteRef` has a
// different digest than the local one. This check can be useful to check for
// updates on remote registries.
-func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageReference) (bool, error) {
+func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageReference, options *HasDifferentDigestOptions) (bool, error) {
// We need to account for the arch that the image uses. It seems
// common on ARM to tweak this option to pull the correct image. See
// github.com/containers/podman/issues/6613.
@@ -738,6 +762,14 @@ func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageRef
sys.VariantChoice = inspectInfo.Variant
}
+ if options != nil && options.AuthFilePath != "" {
+ sys.AuthFilePath = options.AuthFilePath
+ }
+
+ return i.hasDifferentDigestWithSystemContext(ctx, remoteRef, sys)
+}
+
+func (i *Image) hasDifferentDigestWithSystemContext(ctx context.Context, remoteRef types.ImageReference, sys *types.SystemContext) (bool, error) {
remoteImg, err := remoteRef.NewImage(ctx, sys)
if err != nil {
return false, err
@@ -869,12 +901,12 @@ func getImageID(ctx context.Context, src types.ImageReference, sys *types.System
}
defer func() {
if err := newImg.Close(); err != nil {
- logrus.Errorf("failed to close image: %q", err)
+ logrus.Errorf("Failed to close image: %q", err)
}
}()
imageDigest := newImg.ConfigInfo().Digest
if err = imageDigest.Validate(); err != nil {
- return "", errors.Wrapf(err, "error getting config info")
+ return "", errors.Wrapf(err, "getting config info")
}
return "@" + imageDigest.Encoded(), nil
}
diff --git a/vendor/github.com/containers/common/libimage/load.go b/vendor/github.com/containers/common/libimage/load.go
index 33dc1a22f..f2b57c43a 100644
--- a/vendor/github.com/containers/common/libimage/load.go
+++ b/vendor/github.com/containers/common/libimage/load.go
@@ -2,7 +2,7 @@ package libimage
import (
"context"
- "errors"
+ "fmt"
"os"
"time"
@@ -28,66 +28,69 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) (
defer r.writeEvent(&Event{ID: "", Name: path, Time: time.Now(), Type: EventTypeImageLoad})
}
- var (
- loadedImages []string
- loadError error
- )
-
if options == nil {
options = &LoadOptions{}
}
- for _, f := range []func() ([]string, error){
+ var loadErrors []error
+
+ for _, f := range []func() ([]string, string, error){
// OCI
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI directory", path)
ref, err := ociTransport.NewReference(path, "")
if err != nil {
- return nil, err
+ return nil, ociTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, ociTransport.Transport.Name(), err
},
// OCI-ARCHIVE
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI archive", path)
ref, err := ociArchiveTransport.NewReference(path, "")
if err != nil {
- return nil, err
+ return nil, ociArchiveTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, ociArchiveTransport.Transport.Name(), err
},
// DIR
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker dir", path)
ref, err := dirTransport.NewReference(path)
if err != nil {
- return nil, err
+ return nil, dirTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, dirTransport.Transport.Name(), err
},
// DOCKER-ARCHIVE
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker archive", path)
ref, err := dockerArchiveTransport.ParseReference(path)
if err != nil {
- return nil, err
+ return nil, dockerArchiveTransport.Transport.Name(), err
}
- return r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
- },
-
- // Give a decent error message if nothing above worked.
- func() ([]string, error) {
- return nil, errors.New("payload does not match any of the supported image formats (oci, oci-archive, dir, docker-archive)")
+ images, err := r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
+ return images, dockerArchiveTransport.Transport.Name(), err
},
} {
- loadedImages, loadError = f()
- if loadError == nil {
- return loadedImages, loadError
+ loadedImages, transportName, err := f()
+ if err == nil {
+ return loadedImages, nil
}
- logrus.Debugf("Error loading %s: %v", path, loadError)
+ logrus.Debugf("Error loading %s (%s): %v", path, transportName, err)
+ loadErrors = append(loadErrors, fmt.Errorf("%s: %v", transportName, err))
+ }
+
+ // Give a decent error message if nothing above worked.
+ loadError := fmt.Errorf("payload does not match any of the supported image formats:")
+ for _, err := range loadErrors {
+ loadError = fmt.Errorf("%v\n * %v", loadError, err)
}
return nil, loadError
diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go
index 81b5343c0..8d1abfba9 100644
--- a/vendor/github.com/containers/common/libimage/manifests/manifests.go
+++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go
@@ -125,19 +125,19 @@ func (l *list) SaveToImage(store storage.Store, imageID string, names []string,
if err != nil {
if created {
if _, err2 := store.DeleteImage(img.ID, true); err2 != nil {
- logrus.Errorf("error deleting image %q after failing to save manifest for it", img.ID)
+ logrus.Errorf("Deleting image %q after failing to save manifest for it", img.ID)
}
}
- return "", errors.Wrapf(err, "error saving manifest list to image %q", imageID)
+ return "", errors.Wrapf(err, "saving manifest list to image %q", imageID)
}
err = store.SetImageBigData(imageID, instancesData, instancesBytes, nil)
if err != nil {
if created {
if _, err2 := store.DeleteImage(img.ID, true); err2 != nil {
- logrus.Errorf("error deleting image %q after failing to save instance locations for it", img.ID)
+ logrus.Errorf("Deleting image %q after failing to save instance locations for it", img.ID)
}
}
- return "", errors.Wrapf(err, "error saving instance list to image %q", imageID)
+ return "", errors.Wrapf(err, "saving instance list to image %q", imageID)
}
return imageID, nil
}
@@ -200,7 +200,7 @@ func (l *list) Push(ctx context.Context, dest types.ImageReference, options Push
}
defer func() {
if err2 := policyContext.Destroy(); err2 != nil {
- logrus.Errorf("error destroying signature policy context: %v", err2)
+ logrus.Errorf("Destroying signature policy context: %v", err2)
}
}()
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index 8712a13fd..1c322c37e 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -561,7 +561,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
}
if pullPolicy == config.PullPolicyNewer && localImage != nil {
- isNewer, err := localImage.HasDifferentDigest(ctx, srcRef)
+ isNewer, err := localImage.hasDifferentDigestWithSystemContext(ctx, srcRef, c.systemContext)
if err != nil {
pullErrors = append(pullErrors, err)
continue
diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go
index 42461014d..dabadbec0 100644
--- a/vendor/github.com/containers/common/libimage/runtime.go
+++ b/vendor/github.com/containers/common/libimage/runtime.go
@@ -2,6 +2,7 @@ package libimage
import (
"context"
+ "fmt"
"os"
"strings"
@@ -306,7 +307,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo
if errors.Cause(err) == os.ErrNotExist {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining if an image is a manifest list: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a manifest list: %v, ignoring the error", err)
return image, nil
}
return nil, err
@@ -484,10 +485,16 @@ func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options
return true, nil
}
+// IsExternalContainerFunc allows for checking whether the specified container
+// is an external one. The definition of an external container can be set by
+// callers.
+type IsExternalContainerFunc func(containerID string) (bool, error)
+
// ListImagesOptions allow for customizing listing images.
type ListImagesOptions struct {
// Filters to filter the listed images. Supported filters are
// * after,before,since=image
+ // * containers=true,false,external
// * dangling=true,false
// * intermediate=true,false (useful for pruning images)
// * id=id
@@ -495,6 +502,11 @@ type ListImagesOptions struct {
// * readonly=true,false
// * reference=name[:tag] (wildcards allowed)
Filters []string
+ // IsExternalContainerFunc allows for checking whether the specified
+ // container is an external one (when containers=external filter is
+ // used). The definition of an external container can be set by
+ // callers.
+ IsExternalContainerFunc IsExternalContainerFunc
}
// ListImages lists images in the local container storage. If names are
@@ -525,7 +537,7 @@ func (r *Runtime) ListImages(ctx context.Context, names []string, options *ListI
var filters []filterFunc
if len(options.Filters) > 0 {
- compiledFilters, err := r.compileImageFilters(ctx, options.Filters)
+ compiledFilters, err := r.compileImageFilters(ctx, options)
if err != nil {
return nil, err
}
@@ -550,8 +562,17 @@ type RemoveImagesOptions struct {
// containers using a specific image. By default, all containers in
// the local containers storage will be removed (if Force is set).
RemoveContainerFunc RemoveContainerFunc
+ // IsExternalContainerFunc allows for checking whether the specified
+ // container is an external one (when containers=external filter is
+ // used). The definition of an external container can be set by
+ // callers.
+ IsExternalContainerFunc IsExternalContainerFunc
+ // Remove external containers even when Force is false. Requires
+ // IsExternalContainerFunc to be specified.
+ ExternalContainers bool
// Filters to filter the removed images. Supported filters are
// * after,before,since=image
+ // * containers=true,false,external
// * dangling=true,false
// * intermediate=true,false (useful for pruning images)
// * id=id
@@ -581,6 +602,10 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem
options = &RemoveImagesOptions{}
}
+ if options.ExternalContainers && options.IsExternalContainerFunc == nil {
+ return nil, []error{fmt.Errorf("libimage error: cannot remove external containers without callback")}
+ }
+
// The logic here may require some explanation. Image removal is
// surprisingly complex since it is recursive (intermediate parents are
// removed) and since multiple items in `names` may resolve to the
@@ -635,7 +660,11 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem
}
default:
- filteredImages, err := r.ListImages(ctx, nil, &ListImagesOptions{Filters: options.Filters})
+ options := &ListImagesOptions{
+ IsExternalContainerFunc: options.IsExternalContainerFunc,
+ Filters: options.Filters,
+ }
+ filteredImages, err := r.ListImages(ctx, nil, options)
if err != nil {
appendError(err)
return nil, rmErrors
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
index 4f11e4ed2..735d19493 100644
--- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
@@ -97,22 +97,22 @@ func InstallDefault(name string) error {
}
if err := cmd.Start(); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
return errors.Wrapf(err, "start %s command", apparmorParserPath)
}
if err := p.generateDefault(apparmorParserPath, pipe); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
if cmdErr := cmd.Wait(); cmdErr != nil {
- logrus.Errorf("unable to wait for AppArmor command: %q", cmdErr)
+ logrus.Errorf("Unable to wait for AppArmor command: %q", cmdErr)
}
return errors.Wrap(err, "generate default profile into pipe")
}
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
return errors.Wrap(cmd.Wait(), "wait for AppArmor command")
@@ -252,7 +252,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
if name != "" {
return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
} else {
- logrus.Debug("skipping loading default AppArmor profile (rootless mode)")
+ logrus.Debug("Skipping loading default AppArmor profile (rootless mode)")
return "", nil
}
}
@@ -292,7 +292,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
if err != nil {
return "", errors.Wrapf(err, "install profile %s", name)
}
- logrus.Infof("successfully loaded AppAmor profile %q", name)
+ logrus.Infof("Successfully loaded AppAmor profile %q", name)
} else {
logrus.Infof("AppAmor profile %q is already loaded", name)
}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index b982aa552..3b4c7fa04 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -54,6 +54,8 @@ type Config struct {
Containers ContainersConfig `toml:"containers"`
// Engine specifies how the container engine based on Engine will run
Engine EngineConfig `toml:"engine"`
+ // Machine specifies configurations of podman machine VMs
+ Machine MachineConfig `toml:"machine"`
// Network section defines the configuration of CNI Plugins
Network NetworkConfig `toml:"network"`
// Secret section defines configurations for the secret management
@@ -281,9 +283,6 @@ type EngineConfig struct {
// MachineEnabled indicates if Podman is running in a podman-machine VM
MachineEnabled bool `toml:"machine_enabled,omitempty"`
- // MachineImage is the image used when creating a podman-machine VM
- MachineImage string `toml:"machine_image,omitempty"`
-
// MultiImageArchive - if true, the container engine allows for storing
// archives (e.g., of the docker-archive transport) with multiple
// images. By default, Podman creates single-image archives.
@@ -335,7 +334,7 @@ type EngineConfig struct {
// ActiveService index to Destinations added v2.0.3
ActiveService string `toml:"active_service,omitempty"`
- // Destinations mapped by service Names
+ // ServiceDestinations mapped by service Names
ServiceDestinations map[string]Destination `toml:"service_destinations,omitempty"`
// RuntimePath is the path to OCI runtime binary for launching containers.
@@ -379,6 +378,10 @@ type EngineConfig struct {
// containers/storage. As such this is not exposed via the config file.
StateType RuntimeStateStore `toml:"-"`
+ // ServiceTimeout is the number of seconds to wait without a connection
+ // before the `podman system service` times out and exits
+ ServiceTimeout uint `toml:"service_timeout,omitempty"`
+
// StaticDir is the path to a persistent directory to store container
// files.
StaticDir string `toml:"static_dir,omitempty"`
@@ -486,6 +489,18 @@ type SecretConfig struct {
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.
+ CPUs uint64 `toml:"cpus,omitempty"`
+ // DiskSize is the size of the disk in GB created when init-ing a podman-machine VM
+ DiskSize uint64 `toml:"disk_size,omitempty"`
+ // MachineImage is the image used when init-ing a podman-machine VM
+ Image string `toml:"image,omitempty"`
+ // Memory in MB a machine is created with.
+ Memory uint64 `toml:"memory,omitempty"`
+}
+
// Destination represents destination for remote service
type Destination struct {
// URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index dc38f8ec6..1d3c003e3 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -396,10 +396,6 @@ default_sysctls = [
#
#machine_enabled = false
-# The image used when creating a podman-machine VM.
-#
-#machine_image = "testing"
-
# MultiImageArchive - if true, the container engine allows for storing archives
# (e.g., of the docker-archive transport) with multiple images. By default,
# Podman creates single-image archives.
@@ -422,7 +418,7 @@ default_sysctls = [
# Default options to pass to the slirp4netns binary.
# For example "allow_host_loopback=true"
#
-#network_cmd_options = []
+#network_cmd_options = ["enable_ipv6=true",]
# Whether to use chroot instead of pivot_root in the runtime
#
@@ -466,6 +462,11 @@ default_sysctls = [
# container/storage tmp directory will be used.
# image_copy_tmp_dir="/var/tmp"
+# Number of seconds to wait without a connection
+# before the `podman system service` times out and exits
+#
+#service_timeout = 5
+
# Directory for persistent engine files (database, etc)
# By default, this will be configured relative to where the containers/storage
# stores containers
@@ -554,8 +555,25 @@ default_sysctls = [
[engine.volume_plugins]
#testplugin = "/run/podman/plugins/test.sock"
-# The [engine.volume_plugins] table MUST be the last entry in this file.
+[machine]
+# Number of CPU's a machine is created with.
+#
+#cpus=1
+
+# The size of the disk in GB created when init-ing a podman-machine VM.
+#
+#disk_size=10
+
+# The image used when creating a podman-machine VM.
+#
+#image = "testing"
+
+# Memory in MB a machine is created with.
+#
+#memory=2048
+
+# The [machine] table MUST be the last entry in this file.
# (Unless another table is added)
# TOML does not provide a way to end a table other than a further table being
-# defined, so every key hereafter will be part of [volume_plugins] and not the
+# defined, so every key hereafter will be part of [machine] and not the
# main config.
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 5ce73bd2a..e72e1b3e4 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -198,7 +198,6 @@ func DefaultConfig() (*Config, error) {
TZ: "",
Umask: "0022",
UTSNS: "private",
- UserNS: "host",
UserNSSize: DefaultUserNSSize,
},
Network: NetworkConfig{
@@ -209,6 +208,7 @@ func DefaultConfig() (*Config, error) {
},
Engine: *defaultEngineConfig,
Secrets: defaultSecretConfig(),
+ Machine: defaultMachineConfig(),
}, nil
}
@@ -220,6 +220,16 @@ func defaultSecretConfig() SecretConfig {
}
}
+// defaultMachineConfig returns the default machine configuration.
+func defaultMachineConfig() MachineConfig {
+ return MachineConfig{
+ CPUs: 1,
+ DiskSize: 10,
+ Image: "testing",
+ Memory: 2048,
+ }
+}
+
// defaultConfigFromMemory returns a default engine configuration. Note that the
// config is different for root and rootless. It also parses the storage.conf.
func defaultConfigFromMemory() (*EngineConfig, error) {
@@ -257,8 +267,11 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
c.ImageBuildFormat = "oci"
c.CgroupManager = defaultCgroupManager()
+ c.ServiceTimeout = uint(5)
c.StopTimeout = uint(10)
-
+ c.NetworkCmdOptions = []string{
+ "enable_ipv6=true",
+ }
c.Remote = isRemote()
c.OCIRuntimes = map[string][]string{
"crun": {
@@ -343,8 +356,6 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
// constants.
c.LockType = "shm"
c.MachineEnabled = false
- c.MachineImage = "testing"
-
c.ChownCopiedFiles = true
return c, nil
@@ -564,9 +575,3 @@ func (c *Config) MachineEnabled() bool {
func (c *Config) RootlessNetworking() string {
return c.Containers.RootlessNetworking
}
-
-// MachineImage returns the image to be
-// used when creating a podman-machine VM
-func (c *Config) MachineImage() string {
- return c.Engine.MachineImage
-}
diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go
index 8eb2da975..43e3a6688 100644
--- a/vendor/github.com/containers/common/pkg/retry/retry.go
+++ b/vendor/github.com/containers/common/pkg/retry/retry.go
@@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
if retryOptions.Delay != 0 {
delay = retryOptions.Delay
}
- logrus.Warnf("failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
+ logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
select {
case <-time.After(delay):
break
diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go
index 2e7802369..aea983cb1 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secrets.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go
@@ -24,8 +24,8 @@ const secretIDLength = 25
// errInvalidPath indicates that the secrets path is invalid
var errInvalidPath = errors.New("invalid secrets path")
-// errNoSuchSecret indicates that the secret does not exist
-var errNoSuchSecret = errors.New("no such secret")
+// ErrNoSuchSecret indicates that the secret does not exist
+var ErrNoSuchSecret = errors.New("no such secret")
// errSecretNameInUse indicates that the secret name is already in use
var errSecretNameInUse = errors.New("secret name in use")
@@ -152,7 +152,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, driv
newID = newID[0:secretIDLength]
_, err := s.lookupSecret(newID)
if err != nil {
- if errors.Cause(err) == errNoSuchSecret {
+ if errors.Cause(err) == ErrNoSuchSecret {
secr.ID = newID
break
} else {
diff --git a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
index 1395d103c..0c4929995 100644
--- a/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
+++ b/vendor/github.com/containers/common/pkg/secrets/secretsdb.go
@@ -71,14 +71,14 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
name, id, err = s.getExactNameAndID(nameOrID)
if err == nil {
return name, id, nil
- } else if errors.Cause(err) != errNoSuchSecret {
+ } else if errors.Cause(err) != ErrNoSuchSecret {
return "", "", err
}
// ID prefix may have been given, iterate through all IDs.
// ID and partial ID has a max length of 25, so we return if its greater than that.
if len(nameOrID) > secretIDLength {
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
exists := false
var foundID, foundName string
@@ -96,7 +96,7 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
if exists {
return foundName, foundID, nil
}
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// getExactNameAndID takes a secret's name or ID and returns both its name and full ID.
@@ -115,7 +115,7 @@ func (s *SecretsManager) getExactNameAndID(nameOrID string) (name, id string, er
return name, id, nil
}
- return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// exactSecretExists checks if the secret exists, given a name or ID
@@ -123,7 +123,7 @@ func (s *SecretsManager) getExactNameAndID(nameOrID string) (name, id string, er
func (s *SecretsManager) exactSecretExists(nameOrID string) (bool, error) {
_, _, err := s.getExactNameAndID(nameOrID)
if err != nil {
- if errors.Cause(err) == errNoSuchSecret {
+ if errors.Cause(err) == ErrNoSuchSecret {
return false, nil
}
return false, err
@@ -158,7 +158,7 @@ func (s *SecretsManager) lookupSecret(nameOrID string) (*Secret, error) {
return &secret, nil
}
- return nil, errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
+ return nil, errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
}
// Store creates a new secret in the secrets database.
diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
index 4b7253b31..6c9321e73 100644
--- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
+++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
@@ -114,13 +114,13 @@ func getMounts(filePath string) []string {
file, err := os.Open(filePath)
if err != nil {
// This is expected on most systems
- logrus.Debugf("file %q not found, skipping...", filePath)
+ logrus.Debugf("File %q not found, skipping...", filePath)
return nil
}
defer file.Close()
scanner := bufio.NewScanner(file)
if err = scanner.Err(); err != nil {
- logrus.Errorf("error reading file %q, %v skipping...", filePath, err)
+ logrus.Errorf("Reading file %q, %v skipping...", filePath, err)
return nil
}
var mounts []string
@@ -128,7 +128,7 @@ func getMounts(filePath string) []string {
if strings.HasPrefix(strings.TrimSpace(scanner.Text()), "/") {
mounts = append(mounts, scanner.Text())
} else {
- logrus.Debugf("skipping unrecognized mount in %v: %q",
+ logrus.Debugf("Skipping unrecognized mount in %v: %q",
filePath, scanner.Text())
}
}
@@ -176,7 +176,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
if _, err := os.Stat(file); err == nil {
mounts, err := addSubscriptionsFromMountsFile(file, mountLabel, containerWorkingDir, uid, gid)
if err != nil {
- logrus.Warnf("error mounting subscriptions, skipping entry in %s: %v", file, err)
+ logrus.Warnf("Failed to mount subscriptions, skipping entry in %s: %v", file, err)
}
subscriptionMounts = mounts
break
@@ -192,7 +192,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
switch {
case err == nil:
if err := addFIPSModeSubscription(&subscriptionMounts, containerWorkingDir, mountPoint, mountLabel, uid, gid); err != nil {
- logrus.Errorf("error adding FIPS mode subscription to container: %v", err)
+ logrus.Errorf("Adding FIPS mode subscription to container: %v", err)
}
case os.IsNotExist(err):
logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode subscription")
diff --git a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
index a36c3eda4..196176a1c 100644
--- a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
+++ b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
@@ -83,12 +83,12 @@ func (s *supplementedImageReference) NewImageSource(ctx context.Context, sys *ty
if iss != nil {
// The composite source has been created. Use its Close method.
if err2 := iss.Close(); err2 != nil {
- logrus.Errorf("error opening image: %v", err2)
+ logrus.Errorf("Opening image: %v", err2)
}
} else if top != nil {
// The composite source has not been created, but the top was already opened. Close it.
if err2 := top.Close(); err2 != nil {
- logrus.Errorf("error opening image: %v", err2)
+ logrus.Errorf("Closing image: %v", err2)
}
}
}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
index 1935d71f1..6420ba274 100644
--- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
@@ -237,7 +237,7 @@ func checkCgroupPids(cgMounts map[string]string, quiet bool) cgroupPids {
_, ok := cgMounts["pids"]
if !ok {
if !quiet {
- logrus.Warn("unable to find pids cgroup in mounts")
+ logrus.Warn("Unable to find pids cgroup in mounts")
}
return cgroupPids{}
}
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index ba4dda5e6..b6ceabce5 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.44.1-dev"
+const Version = "0.46.1-dev"
diff --git a/vendor/github.com/containers/psgo/.codespellrc b/vendor/github.com/containers/psgo/.codespellrc
new file mode 100644
index 000000000..604bc21da
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.codespellrc
@@ -0,0 +1,2 @@
+[codespell]
+skip = ./vendor,./.git
diff --git a/vendor/github.com/containers/psgo/.golangci.yml b/vendor/github.com/containers/psgo/.golangci.yml
new file mode 100644
index 000000000..a098068fe
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.golangci.yml
@@ -0,0 +1,6 @@
+# For documentation, see https://golangci-lint.run/usage/configuration/
+
+linters:
+ enable:
+ - errorlint
+ - gofumpt
diff --git a/vendor/github.com/containers/psgo/.travis.yml b/vendor/github.com/containers/psgo/.travis.yml
deleted file mode 100644
index c07bb140b..000000000
--- a/vendor/github.com/containers/psgo/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: go
-
-sudo: required
-
-servics:
- - docker
-
-go:
- - tip
-
-before_install:
- - sudo add-apt-repository ppa:duggan/bats --yes
- - sudo apt-get update -qq
- - sudo apt-get install -qq bats
-
-script:
- - make validate
- - make build
- - make test
diff --git a/vendor/github.com/containers/psgo/Makefile b/vendor/github.com/containers/psgo/Makefile
index 831dfa31f..fb6126e7c 100644
--- a/vendor/github.com/containers/psgo/Makefile
+++ b/vendor/github.com/containers/psgo/Makefile
@@ -1,28 +1,25 @@
-export GO111MODULE=off
-export GOPROXY=https://proxy.golang.org
-
SHELL= /bin/bash
GO ?= go
BUILD_DIR := ./bin
BIN_DIR := /usr/local/bin
NAME := psgo
-PROJECT := github.com/containers/psgo
BATS_TESTS := *.bats
-GO_SRC=$(shell find . -name \*.go)
-GO_BUILD=$(GO) build
-# Go module support: set `-mod=vendor` to use the vendored sources
-ifeq ($(shell go help mod >/dev/null 2>&1 && echo true), true)
- GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
+# Not all platforms support -buildmode=pie, plus it's incompatible with -race.
+ifeq ($(shell $(GO) env GOOS),linux)
+ ifeq (,$(filter $(shell $(GO) env GOARCH),mips mipsle mips64 mips64le ppc64 riscv64))
+ ifeq (,$(findstring -race,$(EXTRA_BUILD_FLAGS)))
+ GO_BUILDMODE := "-buildmode=pie"
+ endif
+ endif
endif
-
-GOBIN ?= $(GO)/bin
+GO_BUILD := $(GO) build $(GO_BUILDMODE)
all: validate build
.PHONY: build
-build: $(GO_SRC)
- $(GO_BUILD) -buildmode=pie -o $(BUILD_DIR)/$(NAME) $(PROJECT)/sample
+build:
+ $(GO_BUILD) $(EXTRA_BUILD_FLAGS) -o $(BUILD_DIR)/$(NAME) ./sample
.PHONY: clean
clean:
@@ -30,13 +27,13 @@ clean:
.PHONY: vendor
vendor:
- GO111MODULE=on go mod tidy
- GO111MODULE=on go mod vendor
- GO111MODULE=on go mod verify
+ go mod tidy
+ go mod vendor
+ go mod verify
.PHONY: validate
-validate: .install.lint
- $(GOBIN)/golangci-lint run
+validate:
+ golangci-lint run
.PHONY: test
test: test-unit test-integration
@@ -47,17 +44,12 @@ test-integration:
.PHONY: test-unit
test-unit:
- go test -v $(PROJECT)
- go test -v $(PROJECT)/internal/...
+ $(GO) test -v $(EXTRA_TEST_FLAGS) ./...
.PHONY: install
install:
sudo install -D -m755 $(BUILD_DIR)/$(NAME) $(BIN_DIR)
-.PHONY: .install.lint
-.install.lint:
- VERSION=1.24.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
-
.PHONY: uninstall
uninstall:
sudo rm $(BIN_DIR)/$(NAME)
diff --git a/vendor/github.com/containers/psgo/README.md b/vendor/github.com/containers/psgo/README.md
index fed42c683..684c80a0c 100644
--- a/vendor/github.com/containers/psgo/README.md
+++ b/vendor/github.com/containers/psgo/README.md
@@ -73,8 +73,12 @@ The ps library is compatible with all AIX format descriptors of the ps command-l
- Set of inheritable capabilities. See capabilities(7) for more information.
- **capprm**
- Set of permitted capabilities. See capabilities(7) for more information.
+- **groups**
+ - Supplmentary groups inside the container.
- **hgroup**
- The corresponding effective group of a container process on the host.
+- **hgroups**
+ - Supplmentary groups on the host.
- **hpid**
- The corresponding host PID of a container process.
- **huser**
diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod
index 699874cf7..fd19d9b48 100644
--- a/vendor/github.com/containers/psgo/go.mod
+++ b/vendor/github.com/containers/psgo/go.mod
@@ -1,10 +1,9 @@
module github.com/containers/psgo
-go 1.13
+go 1.14
require (
github.com/opencontainers/runc v1.0.2
- github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
)
diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum
index 0ba04956f..85b0f4ff7 100644
--- a/vendor/github.com/containers/psgo/go.sum
+++ b/vendor/github.com/containers/psgo/go.sum
@@ -39,7 +39,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
diff --git a/vendor/github.com/containers/psgo/internal/host/host.go b/vendor/github.com/containers/psgo/internal/host/host.go
index 33ad67a11..3c708a2b8 100644
--- a/vendor/github.com/containers/psgo/internal/host/host.go
+++ b/vendor/github.com/containers/psgo/internal/host/host.go
@@ -54,7 +54,7 @@ func BootTime() (int64, error) {
btimeSec, err := strconv.ParseInt(btimeStr, 10, 64)
if err != nil {
- return 0, fmt.Errorf("error parsing boot time from /proc/stat: %s", err)
+ return 0, fmt.Errorf("error parsing boot time from /proc/stat: %w", err)
}
bootTime = &btimeSec
return btimeSec, nil
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 4778048f2..28ee6a2c9 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -59,7 +59,7 @@ func ReadMappings(path string) ([]IDMap, error) {
for {
line, _, err := buf.ReadLine()
if err != nil {
- if err == io.EOF {
+ if err == io.EOF { //nolint:errorlint // False positive, see https://github.com/polyfloyd/go-errorlint/pull/12
return mappings, nil
}
return nil, fmt.Errorf("cannot read line from %s: %w", path, err)
diff --git a/vendor/github.com/containers/psgo/internal/proc/pids.go b/vendor/github.com/containers/psgo/internal/proc/pids.go
index 69e8befc1..2687396e1 100644
--- a/vendor/github.com/containers/psgo/internal/proc/pids.go
+++ b/vendor/github.com/containers/psgo/internal/proc/pids.go
@@ -52,7 +52,7 @@ func GetPIDs() ([]string, error) {
return pids, nil
}
-// GetPIDsFromCgroup returns a strings slice of all pids listesd in pid's pids
+// GetPIDsFromCgroup returns a strings slice of all pids listed in pid's pids
// cgroup. It automatically detects if we're running in unified mode or not.
func GetPIDsFromCgroup(pid string) ([]string, error) {
unified, err := cgroups.IsCgroup2UnifiedMode()
@@ -65,11 +65,12 @@ func GetPIDsFromCgroup(pid string) ([]string, error) {
return getPIDsFromCgroupV1(pid)
}
-// getPIDsFromCgroupV1 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV1 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV1(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
- f, err := os.Open(fmt.Sprintf("/proc/%s/cgroup", pid))
+ pidPath := fmt.Sprintf("/proc/%s/cgroup", pid)
+ f, err := os.Open(pidPath)
if err != nil {
return nil, err
}
@@ -83,7 +84,8 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
continue
}
if fields[1] == "pids" {
- cgroupPath = fmt.Sprintf("/sys/fs/cgroup/pids/%s/cgroup.procs", fields[2])
+ cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", fields[2], "cgroup.procs")
+ break
}
}
@@ -94,7 +96,18 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
// Second, extract the PIDs inside the cgroup.
f, err = os.Open(cgroupPath)
if err != nil {
- return nil, err
+ if os.IsNotExist(err) {
+ // OCI runtimes might mount the container cgroup at the root, breaking what it showed
+ // in /proc/$PID/cgroup and the path.
+ // Check if the PID still exists to make sure the process is still alive.
+ if _, errStat := os.Stat(pidPath); errStat == nil {
+ cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", "cgroup.procs")
+ f, err = os.Open(cgroupPath)
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
}
defer f.Close()
@@ -107,7 +120,7 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
return pids, nil
}
-// getPIDsFromCgroupV2 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV2 returns a strings slice of all pids listed in pid's pids
// cgroup.
func getPIDsFromCgroupV2(pid string) ([]string, error) {
// First, find the corresponding path to the PID cgroup.
@@ -124,8 +137,10 @@ func getPIDsFromCgroupV2(pid string) ([]string, error) {
if len(fields) != 3 {
continue
}
- cgroupSlice = fields[2]
- break
+ if fields[1] == "" {
+ cgroupSlice = fields[2]
+ break
+ }
}
if cgroupSlice == "" {
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 2753915fd..1896b5c07 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -182,7 +182,7 @@ func readStatusUserNS(pid string) ([]string, error) {
c := exec.Command(args[0], args[1:]...)
output, err := c.CombinedOutput()
if err != nil {
- return nil, fmt.Errorf("error executing %q: %v", strings.Join(args, " "), err)
+ return nil, fmt.Errorf("error executing %q: %w", strings.Join(args, " "), err)
}
return strings.Split(string(output), "\n"), nil
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index 8fd49e416..715039610 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -215,7 +215,7 @@ func (p *Process) StartTime() (time.Time, error) {
return time.Unix(sinceBoot+bootTime, 0), nil
}
-// CPUTime returns the cumlative CPU time of process p as a time.Duration.
+// CPUTime returns the cumulative CPU time of process p as a time.Duration.
func (p *Process) CPUTime() (time.Duration, error) {
user, err := strconv.ParseInt(p.Stat.Utime, 10, 64)
if err != nil {
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index b0569fa1c..ea893e7ca 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -175,6 +175,11 @@ var (
procFn: processGROUP,
},
{
+ normal: "groups",
+ header: "GROUPS",
+ procFn: processGROUPS,
+ },
+ {
code: "%P",
normal: "ppid",
header: "PPID",
@@ -306,6 +311,12 @@ var (
procFn: processHGROUP,
},
{
+ normal: "hgroups",
+ header: "HGROUPS",
+ onHost: true,
+ procFn: processHGROUPS,
+ },
+ {
normal: "rss",
header: "RSS",
procFn: processRSS,
@@ -620,14 +631,29 @@ func findHostProcess(p *process.Process, ctx *psContext) *process.Process {
}
// processGROUP returns the effective group ID of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[1])
}
+// processGROUPS returns the supplementary groups of the process separated by
+// comma. This will be the textual group ID, if it can be obtained, or a
+// decimal representation otherwise.
+func processGROUPS(p *process.Process, ctx *psContext) (string, error) {
+ var err error
+ groups := make([]string, len(p.Status.Groups))
+ for i, g := range p.Status.Groups {
+ groups[i], err = process.LookupGID(g)
+ if err != nil {
+ return "", err
+ }
+ }
+ return strings.Join(groups, ","), nil
+}
+
// processRGROUP returns the real group ID of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
// otherwise.
func processRGROUP(p *process.Process, ctx *psContext) (string, error) {
return process.LookupGID(p.Status.Gids[0])
@@ -639,14 +665,14 @@ func processPPID(p *process.Process, ctx *psContext) (string, error) {
}
// processUSER returns the effective user name of the process. This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[1])
}
// processRUSER returns the effective user name of the process. This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
// otherwise.
func processRUSER(p *process.Process, ctx *psContext) (string, error) {
return process.LookupUID(p.Status.Uids[0])
@@ -867,6 +893,26 @@ func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
return "?", nil
}
+// processHGROUPS returns the supplementary groups of the corresponding host
+// process of the (container) or "?" if no corresponding process could be
+// found.
+func processHGROUPS(p *process.Process, ctx *psContext) (string, error) {
+ if hp := findHostProcess(p, ctx); hp != nil {
+ groups := hp.Status.Groups
+ if ctx.opts != nil && len(ctx.opts.GIDMap) > 0 {
+ var err error
+ for i, g := range groups {
+ groups[i], err = findID(g, ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
+ if err != nil {
+ return "", err
+ }
+ }
+ }
+ return strings.Join(groups, ","), nil
+ }
+ return "?", nil
+}
+
// processRSS returns the resident set size of process p in KiB (1024-byte
// units).
func processRSS(p *process.Process, ctx *psContext) (string, error) {
diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml
index 20bede452..d080d790c 100644
--- a/vendor/github.com/containers/storage/.cirrus.yml
+++ b/vendor/github.com/containers/storage/.cirrus.yml
@@ -20,16 +20,14 @@ env:
FEDORA_NAME: "fedora-34"
PRIOR_FEDORA_NAME: "fedora-33"
UBUNTU_NAME: "ubuntu-2104"
- PRIOR_UBUNTU_NAME: "ubuntu-2010"
# GCE project where images live
IMAGE_PROJECT: "libpod-218412"
# VM Image built in containers/automation_images
- _BUILT_IMAGE_SUFFIX: "c6248193773010944"
+ _BUILT_IMAGE_SUFFIX: "c6431352024203264"
FEDORA_CACHE_IMAGE_NAME: "fedora-${_BUILT_IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${_BUILT_IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${_BUILT_IMAGE_SUFFIX}"
- PRIOR_UBUNTU_CACHE_IMAGE_NAME: "prior-ubuntu-${_BUILT_IMAGE_SUFFIX}"
####
#### Command variables to help avoid duplication
@@ -115,15 +113,6 @@ ubuntu_testing_task: &ubuntu_testing
TEST_DRIVER: "overlay"
-prior_ubuntu_testing_task:
- <<: *ubuntu_testing
- alias: prior_ubuntu_testing
- name: *std_test_name
- env:
- OS_NAME: "${PRIOR_UBUNTU_NAME}"
- VM_IMAGE: "${PRIOR_UBUNTU_CACHE_IMAGE_NAME}"
-
-
lint_task:
env:
CIRRUS_WORKING_DIR: "/go/src/github.com/containers/storage"
@@ -153,7 +142,6 @@ meta_task:
${FEDORA_CACHE_IMAGE_NAME}
${PRIOR_FEDORA_CACHE_IMAGE_NAME}
${UBUNTU_CACHE_IMAGE_NAME}
- ${PRIOR_UBUNTU_CACHE_IMAGE_NAME}
BUILDID: "${CIRRUS_BUILD_ID}"
REPOREF: "${CIRRUS_CHANGE_IN_REPO}"
GCPJSON: ENCRYPTED[244a93fe8b386b48b96f748342bf741350e43805eee81dd04b45093bdf737e540b993fc735df41f131835fa0f9b65826]
@@ -181,7 +169,6 @@ success_task:
- fedora_testing
- prior_fedora_testing
- ubuntu_testing
- - prior_ubuntu_testing
- meta
- vendor
container:
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 39fc130ef..afc132ffa 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.36.0
+1.36.0+dev
diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
index 76f12ec3b..a566fbffa 100644
--- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go
+++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
@@ -730,14 +730,14 @@ func useDirperm() bool {
enableDirpermLock.Do(func() {
base, err := ioutil.TempDir("", "storage-aufs-base")
if err != nil {
- logrus.Errorf("error checking dirperm1: %v", err)
+ logrus.Errorf("Checking dirperm1: %v", err)
return
}
defer os.RemoveAll(base)
union, err := ioutil.TempDir("", "storage-aufs-union")
if err != nil {
- logrus.Errorf("error checking dirperm1: %v", err)
+ logrus.Errorf("Checking dirperm1: %v", err)
return
}
defer os.RemoveAll(union)
@@ -748,7 +748,7 @@ func useDirperm() bool {
}
enableDirperm = true
if err := Unmount(union); err != nil {
- logrus.Errorf("error checking dirperm1: failed to unmount %v", err)
+ logrus.Errorf("Checking dirperm1: failed to unmount %v", err)
}
})
return enableDirperm
diff --git a/vendor/github.com/containers/storage/drivers/fsdiff.go b/vendor/github.com/containers/storage/drivers/fsdiff.go
index c52788509..a534630df 100644
--- a/vendor/github.com/containers/storage/drivers/fsdiff.go
+++ b/vendor/github.com/containers/storage/drivers/fsdiff.go
@@ -180,7 +180,7 @@ func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, options ApplyDiffOpts)
start := time.Now().UTC()
logrus.Debug("Start untar layer")
if size, err = ApplyUncompressedLayer(layerFs, options.Diff, tarOptions); err != nil {
- logrus.Errorf("Error while applying layer: %s", err)
+ logrus.Errorf("While applying layer: %s", err)
return
}
logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index f546f9b10..62130c73e 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -174,21 +174,21 @@ func checkSupportVolatile(home, runhome string) (bool, error) {
var usingVolatile bool
if err == nil {
if volatileCacheResult {
- logrus.Debugf("cached value indicated that volatile is being used")
+ logrus.Debugf("Cached value indicated that volatile is being used")
} else {
- logrus.Debugf("cached value indicated that volatile is not being used")
+ logrus.Debugf("Cached value indicated that volatile is not being used")
}
usingVolatile = volatileCacheResult
} else {
usingVolatile, err = doesVolatile(home)
if err == nil {
if usingVolatile {
- logrus.Debugf("overlay test mount indicated that volatile is being used")
+ logrus.Debugf("overlay: test mount indicated that volatile is being used")
} else {
- logrus.Debugf("overlay test mount indicated that volatile is not being used")
+ logrus.Debugf("overlay: test mount indicated that volatile is not being used")
}
if err = cachedFeatureRecord(runhome, feature, usingVolatile, ""); err != nil {
- return false, errors.Wrap(err, "error recording volatile-being-used status")
+ return false, errors.Wrap(err, "recording volatile-being-used status")
}
}
}
@@ -206,9 +206,9 @@ func checkAndRecordOverlaySupport(fsMagic graphdriver.FsMagic, home, runhome str
overlayCacheResult, overlayCacheText, err := cachedFeatureCheck(runhome, feature)
if err == nil {
if overlayCacheResult {
- logrus.Debugf("cached value indicated that overlay is supported")
+ logrus.Debugf("Cached value indicated that overlay is supported")
} else {
- logrus.Debugf("cached value indicated that overlay is not supported")
+ logrus.Debugf("Cached value indicated that overlay is not supported")
}
supportsDType = overlayCacheResult
if !supportsDType {
@@ -225,12 +225,12 @@ func checkAndRecordOverlaySupport(fsMagic graphdriver.FsMagic, home, runhome str
}
err = errors.Wrap(err, "kernel does not support overlay fs")
if err2 := cachedFeatureRecord(runhome, feature, false, err.Error()); err2 != nil {
- return false, errors.Wrapf(err2, "error recording overlay not being supported (%v)", err)
+ return false, errors.Wrapf(err2, "recording overlay not being supported (%v)", err)
}
return false, err
}
if err = cachedFeatureRecord(runhome, feature, supportsDType, ""); err != nil {
- return false, errors.Wrap(err, "error recording overlay support status")
+ return false, errors.Wrap(err, "recording overlay support status")
}
}
return supportsDType, nil
@@ -310,24 +310,24 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
metacopyCacheResult, _, err := cachedFeatureCheck(runhome, feature)
if err == nil {
if metacopyCacheResult {
- logrus.Debugf("cached value indicated that metacopy is being used")
+ logrus.Debugf("Cached value indicated that metacopy is being used")
} else {
- logrus.Debugf("cached value indicated that metacopy is not being used")
+ logrus.Debugf("Cached value indicated that metacopy is not being used")
}
usingMetacopy = metacopyCacheResult
} else {
usingMetacopy, err = doesMetacopy(home, opts.mountOptions)
if err == nil {
if usingMetacopy {
- logrus.Debugf("overlay test mount indicated that metacopy is being used")
+ logrus.Debugf("overlay: test mount indicated that metacopy is being used")
} else {
- logrus.Debugf("overlay test mount indicated that metacopy is not being used")
+ logrus.Debugf("overlay: test mount indicated that metacopy is not being used")
}
if err = cachedFeatureRecord(runhome, feature, usingMetacopy, ""); err != nil {
- return nil, errors.Wrap(err, "error recording metacopy-being-used status")
+ return nil, errors.Wrap(err, "recording metacopy-being-used status")
}
} else {
- logrus.Infof("overlay test mount did not indicate whether or not metacopy is being used: %v", err)
+ logrus.Infof("overlay: test mount did not indicate whether or not metacopy is being used: %v", err)
return nil, err
}
}
@@ -548,7 +548,7 @@ func SupportsNativeOverlay(graphroot, rundir string) (bool, error) {
}
switch contents {
case "true":
- logrus.Debugf("overlay storage already configured with a mount-program")
+ logrus.Debugf("overlay: storage already configured with a mount-program")
return false, nil
default:
needsMountProgram, err := scanForMountProgramIndicators(home)
@@ -640,17 +640,17 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
flags = fmt.Sprintf("%s,userxattr", flags)
}
if err := syscall.Mknod(filepath.Join(upperDir, "whiteout"), syscall.S_IFCHR|0600, int(unix.Mkdev(0, 0))); err != nil {
- logrus.Debugf("unable to create kernel-style whiteout: %v", err)
+ logrus.Debugf("Unable to create kernel-style whiteout: %v", err)
return supportsDType, errors.Wrapf(err, "unable to create kernel-style whiteout")
}
if len(flags) < unix.Getpagesize() {
err := unix.Mount("overlay", mergedDir, "overlay", 0, flags)
if err == nil {
- logrus.Debugf("overlay test mount with multiple lowers succeeded")
+ logrus.Debugf("overlay: test mount with multiple lowers succeeded")
return supportsDType, nil
}
- logrus.Debugf("overlay test mount with multiple lowers failed %v", err)
+ logrus.Debugf("overlay: test mount with multiple lowers failed %v", err)
}
flags = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lower1Dir, upperDir, workDir)
if selinux.GetEnabled() {
@@ -659,10 +659,10 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
if len(flags) < unix.Getpagesize() {
err := unix.Mount("overlay", mergedDir, "overlay", 0, flags)
if err == nil {
- logrus.StandardLogger().Logf(logLevel, "overlay test mount with multiple lowers failed, but succeeded with a single lower")
+ logrus.StandardLogger().Logf(logLevel, "overlay: test mount with multiple lowers failed, but succeeded with a single lower")
return supportsDType, errors.Wrap(graphdriver.ErrNotSupported, "kernel too old to provide multiple lowers feature for overlay")
}
- logrus.Debugf("overlay test mount with a single lower failed %v", err)
+ logrus.Debugf("overlay: test mount with a single lower failed %v", err)
}
logrus.StandardLogger().Logf(logLevel, "'overlay' is not supported over %s at %q", backingFs, home)
return supportsDType, errors.Wrapf(graphdriver.ErrIncompatibleFS, "'overlay' is not supported over %s at %q", backingFs, home)
@@ -682,9 +682,9 @@ func (d *Driver) useNaiveDiff() bool {
nativeDiffCacheResult, nativeDiffCacheText, err := cachedFeatureCheck(d.runhome, feature)
if err == nil {
if nativeDiffCacheResult {
- logrus.Debugf("cached value indicated that native-diff is usable")
+ logrus.Debugf("Cached value indicated that native-diff is usable")
} else {
- logrus.Debugf("cached value indicated that native-diff is not being used")
+ logrus.Debugf("Cached value indicated that native-diff is not being used")
logrus.Info(nativeDiffCacheText)
}
useNaiveDiffOnly = !nativeDiffCacheResult
@@ -821,7 +821,7 @@ func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts
opts.StorageOpt["inodes"] = strconv.FormatUint(d.options.quota.Inodes, 10)
}
- return d.create(id, parent, opts)
+ return d.create(id, parent, opts, false)
}
// Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
@@ -831,15 +831,16 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
if _, ok := opts.StorageOpt["size"]; ok {
return fmt.Errorf("--storage-opt size is only supported for ReadWrite Layers")
}
+
if _, ok := opts.StorageOpt["inodes"]; ok {
return fmt.Errorf("--storage-opt inodes is only supported for ReadWrite Layers")
}
}
- return d.create(id, parent, opts)
+ return d.create(id, parent, opts, true)
}
-func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) {
+func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disableQuota bool) (retErr error) {
dir := d.dir(id)
uidMaps := d.uidMaps
@@ -880,7 +881,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
}
}()
- if d.quotaCtl != nil {
+ if d.quotaCtl != nil && !disableQuota {
quota := quota.Quota{}
if opts != nil && len(opts.StorageOpt) > 0 {
driver := &Driver{}
@@ -994,7 +995,7 @@ func (d *Driver) getLower(parent string) (string, error) {
}
logrus.Warnf("Can't read parent link %q because it does not exist. Going through storage to recreate the missing links.", path.Join(parentDir, "link"))
if err := d.recreateSymlinks(); err != nil {
- return "", errors.Wrap(err, "error recreating the links")
+ return "", errors.Wrap(err, "recreating the links")
}
parentLink, err = ioutil.ReadFile(path.Join(parentDir, "link"))
if err != nil {
@@ -1038,7 +1039,7 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) {
if os.IsNotExist(err) {
logrus.Warnf("Can't read link %q because it does not exist. A storage corruption might have occurred, attempting to recreate the missing symlinks. It might be best wipe the storage to avoid further errors due to storage corruption.", lower)
if err := d.recreateSymlinks(); err != nil {
- return nil, fmt.Errorf("error recreating the missing symlinks: %v", err)
+ return nil, fmt.Errorf("recreating the missing symlinks: %v", err)
}
// let's call Readlink on lower again now that we have recreated the missing symlinks
lp, err = os.Readlink(lower)
@@ -1121,7 +1122,7 @@ func (d *Driver) recreateSymlinks() error {
// List all the directories under the home directory
dirs, err := ioutil.ReadDir(d.home)
if err != nil {
- return fmt.Errorf("error reading driver home directory %q: %v", d.home, err)
+ return fmt.Errorf("reading driver home directory %q: %v", d.home, err)
}
linksDir := filepath.Join(d.home, "l")
// This makes the link directory if it doesn't exist
@@ -1148,7 +1149,7 @@ func (d *Driver) recreateSymlinks() error {
// Read the "link" file under each layer to get the name of the symlink
data, err := ioutil.ReadFile(path.Join(d.dir(dir.Name()), "link"))
if err != nil {
- errs = multierror.Append(errs, errors.Wrapf(err, "error reading name of symlink for %q", dir))
+ errs = multierror.Append(errs, errors.Wrapf(err, "reading name of symlink for %q", dir))
continue
}
linkPath := path.Join(d.home, linkDir, strings.Trim(string(data), "\n"))
@@ -1162,7 +1163,7 @@ func (d *Driver) recreateSymlinks() error {
}
madeProgress = true
} else if err != nil {
- errs = multierror.Append(errs, errors.Wrapf(err, "error trying to stat %q", linkPath))
+ errs = multierror.Append(errs, err)
continue
}
}
@@ -1170,7 +1171,7 @@ func (d *Driver) recreateSymlinks() error {
// that each symlink we have corresponds to one.
links, err := ioutil.ReadDir(linksDir)
if err != nil {
- errs = multierror.Append(errs, errors.Wrapf(err, "error reading links directory %q", linksDir))
+ errs = multierror.Append(errs, err)
continue
}
// Go through all of the symlinks in the "l" directory
@@ -1178,7 +1179,7 @@ func (d *Driver) recreateSymlinks() error {
// Read the symlink's target, which should be "../$layer/diff"
target, err := os.Readlink(filepath.Join(linksDir, link.Name()))
if err != nil {
- errs = multierror.Append(errs, errors.Wrapf(err, "error reading target of link %q", link))
+ errs = multierror.Append(errs, err)
continue
}
targetComponents := strings.Split(target, string(os.PathSeparator))
@@ -1196,7 +1197,7 @@ func (d *Driver) recreateSymlinks() error {
data, err := ioutil.ReadFile(linkFile)
if err != nil || string(data) != link.Name() {
if err := ioutil.WriteFile(linkFile, []byte(link.Name()), 0644); err != nil {
- errs = multierror.Append(errs, errors.Wrapf(err, "error correcting link for layer %q", targetID))
+ errs = multierror.Append(errs, errors.Wrapf(err, "correcting link for layer %s", targetID))
continue
}
madeProgress = true
@@ -1241,7 +1242,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
if unshare.IsRootless() {
logLevel = logrus.DebugLevel
}
- logrus.StandardLogger().Logf(logLevel, "ignoring metacopy option from storage.conf, not supported with booted kernel")
+ logrus.StandardLogger().Logf(logLevel, "Ignoring metacopy option from storage.conf, not supported with booted kernel")
}
}
}
@@ -1275,7 +1276,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
}
logrus.Warnf("Can't read parent link %q because it does not exist. Going through storage to recreate the missing links.", path.Join(dir, "link"))
if err := d.recreateSymlinks(); err != nil {
- return "", errors.Wrap(err, "error recreating the links")
+ return "", errors.Wrap(err, "recreating the links")
}
link, err = ioutil.ReadFile(path.Join(dir, "link"))
if err != nil {
@@ -1330,7 +1331,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
if lower == "" && os.IsNotExist(err) {
logrus.Warnf("Can't stat lower layer %q because it does not exist. Going through storage to recreate the missing symlinks.", newpath)
if err := d.recreateSymlinks(); err != nil {
- return "", fmt.Errorf("error recreating the missing symlinks: %v", err)
+ return "", fmt.Errorf("Recreating the missing symlinks: %v", err)
}
lower = newpath
} else if lower == "" {
@@ -1381,7 +1382,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
if retErr != nil {
if c := d.ctr.Decrement(mergedDir); c <= 0 {
if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil {
- logrus.Errorf("error unmounting %v: %v", mergedDir, mntErr)
+ logrus.Errorf("Unmounting %v: %v", mergedDir, mntErr)
}
}
}
@@ -1473,7 +1474,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
flags, data := mount.ParseOptions(mountData)
logrus.Debugf("overlay: mount_data=%s", mountData)
if err := mountFunc("overlay", mountTarget, "overlay", uintptr(flags), data); err != nil {
- return "", fmt.Errorf("error creating overlay mount to %s, mount_data=%q: %v", mountTarget, mountData, err)
+ return "", fmt.Errorf("creating overlay mount to %s, mount_data=%q: %v", mountTarget, mountData, err)
}
return mergedDir, nil
@@ -1820,7 +1821,7 @@ func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMapp
err = graphdriver.ChownPathByMaps(layerFs, toContainer, toHost)
if err != nil {
if err2 := d.Put(id); err2 != nil {
- logrus.Errorf("%v; error unmounting %v: %v", err, id, err2)
+ logrus.Errorf("%v; unmounting %v: %v", err, id, err2)
}
return err
}
@@ -1923,7 +1924,7 @@ func (d *Driver) releaseAdditionalLayerByID(id string) {
if al, err := d.getAdditionalLayerPathByID(id); err == nil {
notifyReleaseAdditionalLayer(al)
} else if !os.IsNotExist(err) {
- logrus.Warnf("unexpected error on reading Additional Layer Store pointer %v", err)
+ logrus.Warnf("Unexpected error on reading Additional Layer Store pointer %v", err)
}
}
@@ -2004,10 +2005,10 @@ func notifyUseAdditionalLayer(al string) {
} else if err == nil {
f.Close()
if err := os.Remove(useFile); err != nil {
- logrus.Warnf("failed to remove use file")
+ logrus.Warnf("Failed to remove use file")
}
}
- logrus.Warnf("unexpected error by Additional Layer Store %v during use; GC doesn't seem to be supported", err)
+ logrus.Warnf("Unexpected error by Additional Layer Store %v during use; GC doesn't seem to be supported", err)
}
// notifyReleaseAdditionalLayer notifies Additional Layer Store that we don't use the specified
@@ -2024,7 +2025,7 @@ func notifyReleaseAdditionalLayer(al string) {
if os.IsNotExist(err) {
return
}
- logrus.Warnf("unexpected error by Additional Layer Store %v during release; GC doesn't seem to be supported", err)
+ logrus.Warnf("Unexpected error by Additional Layer Store %v during release; GC doesn't seem to be supported", err)
}
// redirectDiffIfAdditionalLayer checks if the passed diff path is Additional Layer and
diff --git a/vendor/github.com/containers/storage/drivers/overlay/randomid.go b/vendor/github.com/containers/storage/drivers/overlay/randomid.go
index fc565ef0b..736c48b9c 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/randomid.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/randomid.go
@@ -47,7 +47,7 @@ func generateID(l int) string {
if retryOnError(err) && retries < maxretries {
count += n
retries++
- logrus.Errorf("error generating version 4 uuid, retrying: %v", err)
+ logrus.Errorf("Generating version 4 uuid, retrying: %v", err)
continue
}
diff --git a/vendor/github.com/containers/storage/drivers/template.go b/vendor/github.com/containers/storage/drivers/template.go
index 5d80b8865..d40d71cfc 100644
--- a/vendor/github.com/containers/storage/drivers/template.go
+++ b/vendor/github.com/containers/storage/drivers/template.go
@@ -31,7 +31,7 @@ func NaiveCreateFromTemplate(d TemplateDriver, id, template string, templateIDMa
diff, err := d.Diff(template, templateIDMappings, parent, parentIDMappings, opts.MountLabel)
if err != nil {
if err2 := d.Remove(id); err2 != nil {
- logrus.Errorf("error removing layer %q: %v", id, err2)
+ logrus.Errorf("Removing layer %q: %v", id, err2)
}
return err
}
@@ -44,7 +44,7 @@ func NaiveCreateFromTemplate(d TemplateDriver, id, template string, templateIDMa
}
if _, err = d.ApplyDiff(id, parent, applyOptions); err != nil {
if err2 := d.Remove(id); err2 != nil {
- logrus.Errorf("error removing layer %q: %v", id, err2)
+ logrus.Errorf("Removing layer %q: %v", id, err2)
}
return err
}
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 911469182..ac7f45c3f 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -12,14 +12,13 @@ require (
github.com/google/go-intervals v0.0.2
github.com/google/uuid v1.2.0 // indirect
github.com/hashicorp/go-multierror v1.1.1
- github.com/json-iterator/go v1.1.11
- github.com/klauspost/compress v1.13.5
+ github.com/json-iterator/go v1.1.12
+ github.com/klauspost/compress v1.13.6
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.4.1
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
- github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/runc v1.0.2
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index 5cc5da6d3..3da64ce8c 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -115,15 +115,16 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
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.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4=
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/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=
@@ -148,9 +149,8 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
-github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 32ba20685..fbf6ad362 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -1557,7 +1557,7 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
compressor = pgzip.NewWriter(&tsdata)
}
if err := compressor.SetConcurrency(1024*1024, 1); err != nil { // 1024*1024 is the hard-coded default; we're not changing that
- logrus.Infof("error setting compression concurrency threads to 1: %v; ignoring", err)
+ logrus.Infof("Error setting compression concurrency threads to 1: %v; ignoring", err)
}
metadata := storage.NewJSONPacker(compressor)
uncompressed, err := archive.DecompressStream(defragmented)
diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go
index 48e846f7c..76544ff28 100644
--- a/vendor/github.com/containers/storage/pkg/archive/archive.go
+++ b/vendor/github.com/containers/storage/pkg/archive/archive.go
@@ -879,7 +879,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
if include != relFilePath {
matches, err := pm.IsMatch(relFilePath)
if err != nil {
- logrus.Errorf("Error matching %s: %v", relFilePath, err)
+ logrus.Errorf("Matching %s: %v", relFilePath, err)
return err
}
skip = matches
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 7bd804c44..6efc6a4c8 100644
--- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
+++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go
@@ -345,6 +345,56 @@ func getFileDigest(f *os.File) (digest.Digest, error) {
return digester.Digest(), nil
}
+// findFileInOSTreeRepos checks whether the requested file already exist in one of the OSTree repo and copies the file content from there if possible.
+// file is the file to look for.
+// ostreeRepos is a list of OSTree repos.
+// dirfd is an open fd to the destination checkout.
+// useHardLinks defines whether the deduplication can be performed using hard links.
+func findFileInOSTreeRepos(file *internal.FileMetadata, ostreeRepos []string, dirfd int, useHardLinks bool) (bool, *os.File, int64, error) {
+ digest, err := digest.Parse(file.Digest)
+ if err != nil {
+ return false, nil, 0, nil
+ }
+ payloadLink := digest.Encoded() + ".payload-link"
+ if len(payloadLink) < 2 {
+ return false, nil, 0, nil
+ }
+
+ for _, repo := range ostreeRepos {
+ sourceFile := filepath.Join(repo, "objects", payloadLink[:2], payloadLink[2:])
+ st, err := os.Stat(sourceFile)
+ if err != nil || !st.Mode().IsRegular() {
+ continue
+ }
+ if st.Size() != file.Size {
+ continue
+ }
+ fd, err := unix.Open(sourceFile, unix.O_RDONLY|unix.O_NONBLOCK, 0)
+ if err != nil {
+ return false, nil, 0, nil
+ }
+ f := os.NewFile(uintptr(fd), "fd")
+ defer f.Close()
+
+ // check if the open file can be deduplicated with hard links
+ if useHardLinks && !canDedupFileWithHardLink(file, fd, st) {
+ continue
+ }
+
+ dstFile, written, err := copyFileContent(fd, file.Name, dirfd, 0, useHardLinks)
+ if err != nil {
+ return false, nil, 0, nil
+ }
+ return true, dstFile, written, nil
+ }
+ // If hard links deduplication was used and it has failed, try again without hard links.
+ if useHardLinks {
+ return findFileInOSTreeRepos(file, ostreeRepos, dirfd, false)
+ }
+
+ return false, nil, 0, nil
+}
+
// findFileOnTheHost checks whether the requested file already exist on the host and copies the file content from there if possible.
// It is currently implemented to look only at the file with the same path. Ideally it can detect the same content also at different
// paths.
@@ -873,6 +923,9 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
// modifies the source file as well.
useHardLinks := parseBooleanPullOption(&storeOpts, "use_hard_links", false)
+ // List of OSTree repositories to use for deduplication
+ ostreeRepos := strings.Split(storeOpts.PullOptions["ostree_repos"], ":")
+
// Generate the manifest
var toc internal.TOC
if err := json.Unmarshal(c.manifest, &toc); err != nil {
@@ -1009,18 +1062,35 @@ 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(dstFile, mode, &r, options); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
found, dstFile, _, err := findFileInOtherLayers(&r, dirfd, otherLayersCache, c.layersTarget, useHardLinks)
if err != nil {
return output, err
}
- if dstFile != nil {
- if err := setFileAttrs(dstFile, mode, &r, options); err != nil {
- dstFile.Close()
+ if found {
+ if err := finalizeFile(dstFile); err != nil {
return output, err
}
- dstFile.Close()
+ continue
+ }
+
+ found, dstFile, _, err = findFileInOSTreeRepos(&r, ostreeRepos, dirfd, useHardLinks)
+ if err != nil {
+ return output, err
}
if found {
+ if err := finalizeFile(dstFile); err != nil {
+ return output, err
+ }
continue
}
@@ -1029,14 +1099,10 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
if err != nil {
return output, err
}
- if dstFile != nil {
- if err := setFileAttrs(dstFile, mode, &r, options); err != nil {
- dstFile.Close()
+ if found {
+ if err := finalizeFile(dstFile); err != nil {
return output, err
}
- dstFile.Close()
- }
- if found {
continue
}
}
diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go
index 9e0e97bd6..92056c1d5 100644
--- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go
+++ b/vendor/github.com/containers/storage/pkg/fileutils/fileutils_unix.go
@@ -14,7 +14,7 @@ import (
// reading it via /proc filesystem.
func GetTotalUsedFds() int {
if fds, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/fd", os.Getpid())); err != nil {
- logrus.Errorf("Error opening /proc/%d/fd: %s", os.Getpid(), err)
+ logrus.Errorf("%v", err)
} else {
return len(fds)
}
diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
index b224e7b5c..fc080acbe 100644
--- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
+++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
@@ -36,7 +36,7 @@ type lockfile struct {
// necessary.
func openLock(path string, ro bool) (fd int, err error) {
if ro {
- fd, err = unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC, 0)
+ fd, err = unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC|os.O_CREATE, 0)
} else {
fd, err = unix.Open(path,
os.O_RDWR|unix.O_CLOEXEC|os.O_CREATE,
diff --git a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go b/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go
index e2cf30b41..6f0726505 100644
--- a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go
+++ b/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go
@@ -43,7 +43,7 @@ func openNextAvailableLoopback(index int, sparseName string, sparseFile *os.File
var st syscall.Stat_t
err = syscall.Fstat(int(sparseFile.Fd()), &st)
if err != nil {
- logrus.Errorf("Error reading information about loopback file %s: %v", sparseName, err)
+ logrus.Errorf("Reading information about loopback file %s: %v", sparseName, err)
return nil, ErrAttachLoopbackDevice
}
@@ -68,7 +68,7 @@ func openNextAvailableLoopback(index int, sparseName string, sparseFile *os.File
// OpenFile adds O_CLOEXEC
loopFile, err = os.OpenFile(target, os.O_RDWR, 0644)
if err != nil {
- logrus.Errorf("Error opening loopback device: %s", err)
+ logrus.Errorf("Opening loopback device: %s", err)
return nil, ErrAttachLoopbackDevice
}
@@ -90,7 +90,7 @@ func openNextAvailableLoopback(index int, sparseName string, sparseFile *os.File
// device and inode numbers.
dev, ino, err := getLoopbackBackingFile(loopFile)
if err != nil {
- logrus.Errorf("Error getting loopback backing file: %s", err)
+ logrus.Errorf("Getting loopback backing file: %s", err)
return nil, ErrGetLoopbackBackingFile
}
if dev != uint64(st.Dev) || ino != st.Ino {
@@ -125,7 +125,7 @@ func AttachLoopDevice(sparseName string) (loop *os.File, err error) {
// OpenFile adds O_CLOEXEC
sparseFile, err := os.OpenFile(sparseName, os.O_RDWR, 0644)
if err != nil {
- logrus.Errorf("Error opening sparse file %s: %s", sparseName, err)
+ logrus.Errorf("Opening sparse file: %v", err)
return nil, ErrAttachLoopbackDevice
}
defer sparseFile.Close()
@@ -147,7 +147,7 @@ func AttachLoopDevice(sparseName string) (loop *os.File, err error) {
// If the call failed, then free the loopback device
if err := ioctlLoopClrFd(loopFile.Fd()); err != nil {
- logrus.Error("Error while cleaning up the loopback device")
+ logrus.Error("While cleaning up the loopback device")
}
loopFile.Close()
return nil, ErrAttachLoopbackDevice
diff --git a/vendor/github.com/containers/storage/pkg/loopback/loopback.go b/vendor/github.com/containers/storage/pkg/loopback/loopback.go
index f4cf2826e..c9be05776 100644
--- a/vendor/github.com/containers/storage/pkg/loopback/loopback.go
+++ b/vendor/github.com/containers/storage/pkg/loopback/loopback.go
@@ -13,7 +13,7 @@ import (
func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
loopInfo, err := ioctlLoopGetStatus64(file.Fd())
if err != nil {
- logrus.Errorf("Error get loopback backing file: %s", err)
+ logrus.Errorf("Get loopback backing file: %v", err)
return 0, 0, ErrGetLoopbackBackingFile
}
return loopInfo.loDevice, loopInfo.loInode, nil
@@ -22,7 +22,7 @@ func getLoopbackBackingFile(file *os.File) (uint64, uint64, error) {
// SetCapacity reloads the size for the loopback device.
func SetCapacity(file *os.File) error {
if err := ioctlLoopSetCapacity(file.Fd(), 0); err != nil {
- logrus.Errorf("Error loopbackSetCapacity: %s", err)
+ logrus.Errorf("loopbackSetCapacity: %s", err)
return ErrSetCapacity
}
return nil
diff --git a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go
index 76e1e499f..7a68bc39b 100644
--- a/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go
+++ b/vendor/github.com/containers/storage/pkg/parsers/kernel/kernel_unix.go
@@ -35,7 +35,7 @@ func GetKernelVersion() (*VersionInfo, error) {
// the given version.
func CheckKernelVersion(k, major, minor int) bool {
if v, err := GetKernelVersion(); err != nil {
- logrus.Warnf("error getting kernel version: %s", err)
+ logrus.Warnf("Error getting kernel version: %s", err)
} else {
if CompareKernelVersion(*v, VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 {
return false
diff --git a/vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go b/vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go
index 26cd8504c..674e0a0ba 100644
--- a/vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go
+++ b/vendor/github.com/containers/storage/pkg/tarlog/tarlogger.go
@@ -34,7 +34,7 @@ func NewLogger(logger func(*tar.Header)) (io.WriteCloser, error) {
}
// Make sure to avoid writes after the reader has been closed.
if err := reader.Close(); err != nil {
- logrus.Errorf("error closing tarlogger reader: %v", err)
+ logrus.Errorf("Closing tarlogger reader: %v", err)
}
// Unblock the Close().
t.closeMutex.Unlock()
diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
index 96b857543..6d351ce80 100644
--- a/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
@@ -154,7 +154,7 @@ func (c *Cmd) Start() error {
pidString := ""
b := new(bytes.Buffer)
if _, err := io.Copy(b, pidRead); err != nil {
- return errors.Wrapf(err, "error reading child PID")
+ return errors.Wrapf(err, "Reading child PID")
}
pidString = b.String()
pid, err := strconv.Atoi(pidString)
@@ -188,8 +188,8 @@ func (c *Cmd) Start() error {
if len(c.UidMappings) == 0 || len(c.GidMappings) == 0 {
uidmap, gidmap, err := GetHostIDMappings("")
if err != nil {
- fmt.Fprintf(continueWrite, "error reading ID mappings in parent: %v", err)
- return errors.Wrapf(err, "error reading ID mappings in parent")
+ fmt.Fprintf(continueWrite, "Reading ID mappings in parent: %v", err)
+ return errors.Wrapf(err, "Reading ID mappings in parent")
}
if len(c.UidMappings) == 0 {
c.UidMappings = uidmap
@@ -222,8 +222,8 @@ func (c *Cmd) Start() error {
if err == nil {
gidmapSet = true
} else {
- logrus.Warnf("error running newgidmap: %v: %s", err, g.String())
- logrus.Warnf("falling back to single mapping")
+ logrus.Warnf("Error running newgidmap: %v: %s", err, g.String())
+ logrus.Warnf("Falling back to single mapping")
g.Reset()
g.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Getegid())))
}
@@ -271,8 +271,8 @@ func (c *Cmd) Start() error {
if err == nil {
uidmapSet = true
} else {
- logrus.Warnf("error running newuidmap: %v: %s", err, u.String())
- logrus.Warnf("falling back to single mapping")
+ logrus.Warnf("Error running newuidmap: %v: %s", err, u.String())
+ logrus.Warnf("Falling back to single mapping")
u.Reset()
u.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Geteuid())))
}
@@ -407,7 +407,7 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) {
// ID and a range size.
uidmap, gidmap, err = GetSubIDMappings(me.Username, me.Username)
if err != nil {
- logrus.Warnf("error reading allowed ID mappings: %v", err)
+ logrus.Warnf("Reading allowed ID mappings: %v", err)
}
if len(uidmap) == 0 {
logrus.Warnf("Found no UID ranges set aside for user %q in /etc/subuid.", me.Username)
@@ -434,13 +434,13 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) {
// If we have CAP_SYS_ADMIN, then we don't need to create a new namespace in order to be able
// to use unshare(), so don't bother creating a new user namespace at this point.
capabilities, err := capability.NewPid(0)
- bailOnError(err, "error reading the current capabilities sets")
+ bailOnError(err, "Reading the current capabilities sets")
if capabilities.Get(capability.EFFECTIVE, capability.CAP_SYS_ADMIN) {
return
}
// Read the set of ID mappings that we're currently using.
uidmap, gidmap, err = GetHostIDMappings("")
- bailOnError(err, "error reading current ID mappings")
+ bailOnError(err, "Reading current ID mappings")
// Just reuse them.
for i := range uidmap {
uidmap[i].HostID = uidmap[i].ContainerID
@@ -463,7 +463,7 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) {
if _, present := os.LookupEnv("BUILDAH_ISOLATION"); !present {
if err = os.Setenv("BUILDAH_ISOLATION", "rootless"); err != nil {
if err := os.Setenv("BUILDAH_ISOLATION", "rootless"); err != nil {
- logrus.Errorf("error setting BUILDAH_ISOLATION=rootless in environment: %v", err)
+ logrus.Errorf("Setting BUILDAH_ISOLATION=rootless in environment: %v", err)
os.Exit(1)
}
}
@@ -483,7 +483,7 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) {
cmd.GidMappingsEnableSetgroups = true
// Finish up.
- logrus.Debugf("running %+v with environment %+v, UID map %+v, and GID map %+v", cmd.Cmd.Args, os.Environ(), cmd.UidMappings, cmd.GidMappings)
+ logrus.Debugf("Running %+v with environment %+v, UID map %+v, and GID map %+v", cmd.Cmd.Args, os.Environ(), cmd.UidMappings, cmd.GidMappings)
ExecRunnable(cmd, nil)
}
@@ -512,7 +512,7 @@ func ExecRunnable(cmd Runnable, cleanup func()) {
}
}
logrus.Errorf("%v", err)
- logrus.Errorf("(unable to determine exit status)")
+ logrus.Errorf("(Unable to determine exit status)")
exit(1)
}
exit(0)
@@ -523,7 +523,7 @@ func getHostIDMappings(path string) ([]specs.LinuxIDMapping, error) {
var mappings []specs.LinuxIDMapping
f, err := os.Open(path)
if err != nil {
- return nil, errors.Wrapf(err, "error reading ID mappings from %q", path)
+ return nil, errors.Wrapf(err, "Reading ID mappings from %q", path)
}
defer f.Close()
scanner := bufio.NewScanner(f)
@@ -571,7 +571,7 @@ func GetHostIDMappings(pid string) ([]specs.LinuxIDMapping, []specs.LinuxIDMappi
func GetSubIDMappings(user, group string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) {
mappings, err := idtools.NewIDMappings(user, group)
if err != nil {
- return nil, nil, errors.Wrapf(err, "error reading subuid mappings for user %q and subgid mappings for group %q", user, group)
+ return nil, nil, errors.Wrapf(err, "Reading subuid mappings for user %q and subgid mappings for group %q", user, group)
}
var uidmap, gidmap []specs.LinuxIDMapping
for _, m := range mappings.UIDs() {
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 8d6f2c4d7..6f6f69807 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -1131,10 +1131,6 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, crea
if options.HostGIDMapping && len(layer.GIDMap) != 0 {
return false
}
- // If we don't care about the mapping, it's fine.
- if len(options.UIDMap) == 0 && len(options.GIDMap) == 0 {
- return true
- }
// Compare the maps.
return reflect.DeepEqual(layer.UIDMap, options.UIDMap) && reflect.DeepEqual(layer.GIDMap, options.GIDMap)
}
diff --git a/vendor/github.com/containers/storage/types/utils.go b/vendor/github.com/containers/storage/types/utils.go
index b7ab07342..4dd1a786e 100644
--- a/vendor/github.com/containers/storage/types/utils.go
+++ b/vendor/github.com/containers/storage/types/utils.go
@@ -87,7 +87,7 @@ func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, e
if tmpPerUserDir != "" {
if _, err := env.systemLstat(tmpPerUserDir); os.IsNotExist(err) {
if err := os.Mkdir(tmpPerUserDir, 0700); err != nil {
- logrus.Errorf("failed to create temp directory for user: %v", err)
+ logrus.Errorf("Failed to create temp directory for user: %v", err)
} else {
return tmpPerUserDir, nil
}
diff --git a/vendor/github.com/containers/storage/userns.go b/vendor/github.com/containers/storage/userns.go
index 3ada41f73..523c92dc8 100644
--- a/vendor/github.com/containers/storage/userns.go
+++ b/vendor/github.com/containers/storage/userns.go
@@ -43,7 +43,7 @@ func getAdditionalSubIDs(username string) (*idSet, *idSet, error) {
}
mappings, err := idtools.NewIDMappings(username, username)
if err != nil {
- logrus.Errorf("cannot find mappings for user %q: %v", username, err)
+ logrus.Errorf("Cannot find mappings for user %q: %v", username, err)
} else {
uids = getHostIDs(mappings.UIDs())
gids = getHostIDs(mappings.GIDs())
diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE
index 6cd1e9627..87d557477 100644
--- a/vendor/github.com/klauspost/compress/LICENSE
+++ b/vendor/github.com/klauspost/compress/LICENSE
@@ -290,3 +290,15 @@ 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.
+
+-----------------
+
+Files: s2/cmd/internal/filepathx/*
+
+Copyright 2016 The filepathx Authors
+
+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/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md
index 235dc7cc6..3429879eb 100644
--- a/vendor/github.com/klauspost/compress/README.md
+++ b/vendor/github.com/klauspost/compress/README.md
@@ -17,12 +17,17 @@ This package provides various compression algorithms.
# changelog
+* 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)
+ * zstd: pooledZipWriter should return Writers to the same pool [#426](https://github.com/klauspost/compress/pull/426)
+ * Removed golang/snappy as external dependency for tests [#421](https://github.com/klauspost/compress/pull/421)
+
* Aug 12, 2021 (v1.13.4)
* Add [snappy replacement package](https://github.com/klauspost/compress/tree/master/snappy).
* zstd: Fix incorrect encoding in "best" mode [#415](https://github.com/klauspost/compress/pull/415)
* Aug 3, 2021 (v1.13.3)
-
* zstd: Improve Best compression [#404](https://github.com/klauspost/compress/pull/404)
* zstd: Fix WriteTo error forwarding [#411](https://github.com/klauspost/compress/pull/411)
* gzhttp: Return http.HandlerFunc instead of http.Handler. Unlikely breaking change. [#406](https://github.com/klauspost/compress/pull/406)
@@ -31,7 +36,6 @@ This package provides various compression algorithms.
* zstd: use SpeedBestCompression for level >= 10 [#410](https://github.com/klauspost/compress/pull/410)
* Jun 14, 2021 (v1.13.1)
-
* s2: Add full Snappy output support [#396](https://github.com/klauspost/compress/pull/396)
* zstd: Add configurable [Decoder window](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithDecoderMaxWindow) size [#394](https://github.com/klauspost/compress/pull/394)
* gzhttp: Add header to skip compression [#389](https://github.com/klauspost/compress/pull/389)
@@ -64,6 +68,9 @@ This package provides various compression algorithms.
* zstd: Reduce memory usage further when using [WithLowerEncoderMem](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithLowerEncoderMem) [#346](https://github.com/klauspost/compress/pull/346)
* s2: Fix potential problem with amd64 assembly and profilers [#349](https://github.com/klauspost/compress/pull/349)
+<details>
+ <summary>See changes prior to v1.12.1</summary>
+
* Mar 26, 2021 (v1.11.13)
* zstd: Big speedup on small dictionary encodes [#344](https://github.com/klauspost/compress/pull/344) [#345](https://github.com/klauspost/compress/pull/345)
* zstd: Add [WithLowerEncoderMem](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithLowerEncoderMem) encoder option [#336](https://github.com/klauspost/compress/pull/336)
@@ -118,6 +125,7 @@ This package provides various compression algorithms.
* zstd: Add experimental compression [dictionaries](https://github.com/klauspost/compress/tree/master/zstd#dictionaries) [#281](https://github.com/klauspost/compress/pull/281)
* zstd: Fix mixed Write and ReadFrom calls [#282](https://github.com/klauspost/compress/pull/282)
* inflate/gz: Limit variable shifts, ~5% faster decompression [#274](https://github.com/klauspost/compress/pull/274)
+</details>
<details>
<summary>See changes prior to v1.11.0</summary>
diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
index 347ac2c90..a746eb733 100644
--- a/vendor/github.com/klauspost/compress/flate/fast_encoder.go
+++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go
@@ -215,24 +215,15 @@ func (e *fastGen) Reset() {
func matchLen(a, b []byte) int {
b = b[:len(a)]
var checked int
- if len(a) >= 4 {
- // Try 4 bytes first
- if diff := binary.LittleEndian.Uint32(a) ^ binary.LittleEndian.Uint32(b); diff != 0 {
- return bits.TrailingZeros32(diff) >> 3
- }
- // Switch to 8 byte matching.
- checked = 4
- a = a[4:]
- b = b[4:]
- 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)
- }
- checked += 8
- a = a[8:]
- b = b[8:]
+
+ 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)
}
+ checked += 8
+ a = a[8:]
+ b = b[8:]
}
b = b[:len(a)]
for i := range a {
diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go
index 41703bba4..9b7cc8e97 100644
--- a/vendor/github.com/klauspost/compress/huff0/decompress.go
+++ b/vendor/github.com/klauspost/compress/huff0/decompress.go
@@ -344,35 +344,241 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
var buf [256]byte
var off uint8
- shift := (8 - d.actualTableLog) & 7
-
- //fmt.Printf("mask: %b, tl:%d\n", mask, d.actualTableLog)
- for br.off >= 4 {
- br.fillFast()
- v := dt[br.peekByteFast()>>shift]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
-
- v = dt[br.peekByteFast()>>shift]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
-
- v = dt[br.peekByteFast()>>shift]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
-
- v = dt[br.peekByteFast()>>shift]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
-
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
+ switch d.actualTableLog {
+ case 8:
+ const shift = 8 - 8
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 7:
+ const shift = 8 - 7
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 6:
+ const shift = 8 - 6
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 5:
+ const shift = 8 - 5
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 4:
+ const shift = 8 - 4
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 3:
+ const shift = 8 - 3
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 2:
+ const shift = 8 - 2
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
+ }
+ }
+ case 1:
+ const shift = 8 - 1
+ for br.off >= 4 {
+ br.fillFast()
+ v := dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+0] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+1] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+2] = uint8(v.entry >> 8)
+
+ v = dt[uint8(br.value>>(56+shift))]
+ br.advance(uint8(v.entry))
+ buf[off+3] = uint8(v.entry >> 8)
+
+ off += 4
+ if off == 0 {
+ if len(dst)+256 > maxDecodedSize {
+ br.close()
+ return nil, ErrMaxDecodedSizeExceeded
+ }
+ dst = append(dst, buf[:]...)
}
- dst = append(dst, buf[:]...)
}
+ default:
+ return nil, fmt.Errorf("invalid tablelog: %d", d.actualTableLog)
}
if len(dst)+int(off) > maxDecodedSize {
@@ -383,6 +589,8 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
// br < 4, so uint8 is fine
bitsLeft := int8(uint8(br.off)*8 + (64 - br.bitsRead))
+ shift := (8 - d.actualTableLog) & 7
+
for bitsLeft > 0 {
if br.bitsRead >= 64-8 {
for br.off > 0 {
@@ -423,24 +631,24 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
var buf [256]byte
var off uint8
- const shift = 0
+ const shift = 56
//fmt.Printf("mask: %b, tl:%d\n", mask, d.actualTableLog)
for br.off >= 4 {
br.fillFast()
- v := dt[br.peekByteFast()>>shift]
+ v := dt[uint8(br.value>>shift)]
br.advance(uint8(v.entry))
buf[off+0] = uint8(v.entry >> 8)
- v = dt[br.peekByteFast()>>shift]
+ v = dt[uint8(br.value>>shift)]
br.advance(uint8(v.entry))
buf[off+1] = uint8(v.entry >> 8)
- v = dt[br.peekByteFast()>>shift]
+ v = dt[uint8(br.value>>shift)]
br.advance(uint8(v.entry))
buf[off+2] = uint8(v.entry >> 8)
- v = dt[br.peekByteFast()>>shift]
+ v = dt[uint8(br.value>>shift)]
br.advance(uint8(v.entry))
buf[off+3] = uint8(v.entry >> 8)
@@ -474,7 +682,7 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
br.close()
return nil, ErrMaxDecodedSizeExceeded
}
- v := dt[br.peekByteFast()>>shift]
+ v := dt[br.peekByteFast()]
nBits := uint8(v.entry)
br.advance(nBits)
bitsLeft -= int8(nBits)
@@ -709,7 +917,6 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
shift := (8 - d.actualTableLog) & 7
const tlSize = 1 << 8
- const tlMask = tlSize - 1
single := d.dt.single[:tlSize]
// Use temp table to avoid bound checks/append penalty.
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go
index 426b9cac7..2c112a0ab 100644
--- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go
@@ -195,7 +195,6 @@ func (d *Digest) UnmarshalBinary(b []byte) error {
b, d.v4 = consumeUint64(b)
b, d.total = consumeUint64(b)
copy(d.mem[:], b)
- b = b[len(d.mem):]
d.n = int(d.total % uint64(len(d.mem)))
return nil
}
diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go
index 3ddbd5c0b..0ae847f75 100644
--- a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go
+++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.go
@@ -9,4 +9,4 @@ package xxhash
func Sum64(b []byte) uint64
//go:noescape
-func writeBlocks(*Digest, []byte) int
+func writeBlocks(d *Digest, b []byte) int
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 2c9c5357a..be8db5bf7 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
@@ -6,7 +6,7 @@
// Register allocation:
// AX h
-// CX pointer to advance through b
+// SI pointer to advance through b
// DX n
// BX loop end
// R8 v1, k1
@@ -16,39 +16,39 @@
// R12 tmp
// R13 prime1v
// R14 prime2v
-// R15 prime4v
+// DI prime4v
-// round reads from and advances the buffer pointer in CX.
+// round reads from and advances the buffer pointer in SI.
// It assumes that R13 has prime1v and R14 has prime2v.
#define round(r) \
- MOVQ (CX), R12 \
- ADDQ $8, CX \
+ MOVQ (SI), R12 \
+ ADDQ $8, SI \
IMULQ R14, R12 \
ADDQ R12, r \
ROLQ $31, r \
IMULQ R13, r
// mergeRound applies a merge round on the two registers acc and val.
-// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v.
+// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v.
#define mergeRound(acc, val) \
IMULQ R14, val \
ROLQ $31, val \
IMULQ R13, val \
XORQ val, acc \
IMULQ R13, acc \
- ADDQ R15, acc
+ ADDQ DI, acc
// func Sum64(b []byte) uint64
TEXT ·Sum64(SB), NOSPLIT, $0-32
// Load fixed primes.
MOVQ ·prime1v(SB), R13
MOVQ ·prime2v(SB), R14
- MOVQ ·prime4v(SB), R15
+ MOVQ ·prime4v(SB), DI
// Load slice.
- MOVQ b_base+0(FP), CX
+ MOVQ b_base+0(FP), SI
MOVQ b_len+8(FP), DX
- LEAQ (CX)(DX*1), BX
+ LEAQ (SI)(DX*1), BX
// The first loop limit will be len(b)-32.
SUBQ $32, BX
@@ -65,14 +65,14 @@ TEXT ·Sum64(SB), NOSPLIT, $0-32
XORQ R11, R11
SUBQ R13, R11
- // Loop until CX > BX.
+ // Loop until SI > BX.
blockLoop:
round(R8)
round(R9)
round(R10)
round(R11)
- CMPQ CX, BX
+ CMPQ SI, BX
JLE blockLoop
MOVQ R8, AX
@@ -100,16 +100,16 @@ noBlocks:
afterBlocks:
ADDQ DX, AX
- // Right now BX has len(b)-32, and we want to loop until CX > len(b)-8.
+ // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8.
ADDQ $24, BX
- CMPQ CX, BX
+ CMPQ SI, BX
JG fourByte
wordLoop:
// Calculate k1.
- MOVQ (CX), R8
- ADDQ $8, CX
+ MOVQ (SI), R8
+ ADDQ $8, SI
IMULQ R14, R8
ROLQ $31, R8
IMULQ R13, R8
@@ -117,18 +117,18 @@ wordLoop:
XORQ R8, AX
ROLQ $27, AX
IMULQ R13, AX
- ADDQ R15, AX
+ ADDQ DI, AX
- CMPQ CX, BX
+ CMPQ SI, BX
JLE wordLoop
fourByte:
ADDQ $4, BX
- CMPQ CX, BX
+ CMPQ SI, BX
JG singles
- MOVL (CX), R8
- ADDQ $4, CX
+ MOVL (SI), R8
+ ADDQ $4, SI
IMULQ R13, R8
XORQ R8, AX
@@ -138,19 +138,19 @@ fourByte:
singles:
ADDQ $4, BX
- CMPQ CX, BX
+ CMPQ SI, BX
JGE finalize
singlesLoop:
- MOVBQZX (CX), R12
- ADDQ $1, CX
+ MOVBQZX (SI), R12
+ ADDQ $1, SI
IMULQ ·prime5v(SB), R12
XORQ R12, AX
ROLQ $11, AX
IMULQ R13, AX
- CMPQ CX, BX
+ CMPQ SI, BX
JL singlesLoop
finalize:
@@ -179,13 +179,13 @@ TEXT ·writeBlocks(SB), NOSPLIT, $0-40
MOVQ ·prime2v(SB), R14
// Load slice.
- MOVQ arg1_base+8(FP), CX
- MOVQ arg1_len+16(FP), DX
- LEAQ (CX)(DX*1), BX
+ MOVQ b_base+8(FP), SI
+ MOVQ b_len+16(FP), DX
+ LEAQ (SI)(DX*1), BX
SUBQ $32, BX
// Load vN from d.
- MOVQ arg+0(FP), AX
+ MOVQ d+0(FP), AX
MOVQ 0(AX), R8 // v1
MOVQ 8(AX), R9 // v2
MOVQ 16(AX), R10 // v3
@@ -199,7 +199,7 @@ blockLoop:
round(R10)
round(R11)
- CMPQ CX, BX
+ CMPQ SI, BX
JLE blockLoop
// Copy vN back to d.
@@ -208,8 +208,8 @@ blockLoop:
MOVQ R10, 16(AX)
MOVQ R11, 24(AX)
- // The number of bytes written is CX minus the old base pointer.
- SUBQ arg1_base+8(FP), CX
- MOVQ CX, ret+32(FP)
+ // The number of bytes written is SI minus the old base pointer.
+ SUBQ b_base+8(FP), SI
+ MOVQ SI, ret+32(FP)
RET
diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml
deleted file mode 100644
index 604314dd4..000000000
--- a/vendor/github.com/mattn/go-isatty/.travis.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-language: go
-sudo: false
-go:
- - 1.13.x
- - tip
-
-before_install:
- - go get -t -v ./...
-
-script:
- - ./go.test.sh
-
-after_success:
- - bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod
index 605c4c221..c9a20b7f3 100644
--- a/vendor/github.com/mattn/go-isatty/go.mod
+++ b/vendor/github.com/mattn/go-isatty/go.mod
@@ -2,4 +2,4 @@ module github.com/mattn/go-isatty
go 1.12
-require golang.org/x/sys v0.0.0-20200116001909-b77594299b42
+require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go
index 711f28808..39bbcf00f 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go
@@ -1,3 +1,4 @@
+//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine
// +build darwin freebsd openbsd netbsd dragonfly
// +build !appengine
diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go
index ff714a376..31503226f 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_others.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_others.go
@@ -1,4 +1,5 @@
-// +build appengine js nacl
+//go:build appengine || js || nacl || wasm
+// +build appengine js nacl wasm
package isatty
diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go
index c5b6e0c08..bae7f9bb3 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go
@@ -1,3 +1,4 @@
+//go:build plan9
// +build plan9
package isatty
diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go
index bdd5c79a0..0c3acf2dc 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_solaris.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go
@@ -1,5 +1,5 @@
-// +build solaris
-// +build !appengine
+//go:build solaris && !appengine
+// +build solaris,!appengine
package isatty
@@ -8,10 +8,9 @@ import (
)
// IsTerminal returns true if the given file descriptor is a terminal.
-// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
+// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c
func IsTerminal(fd uintptr) bool {
- var termio unix.Termio
- err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
+ _, err := unix.IoctlGetTermio(int(fd), unix.TCGETA)
return err == nil
}
diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go
index 31a1ca973..67787657f 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go
@@ -1,4 +1,5 @@
-// +build linux aix
+//go:build (linux || aix || zos) && !appengine
+// +build linux aix zos
// +build !appengine
package isatty
diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go
index 1fa869154..8e3c99171 100644
--- a/vendor/github.com/mattn/go-isatty/isatty_windows.go
+++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go
@@ -1,5 +1,5 @@
-// +build windows
-// +build !appengine
+//go:build windows && !appengine
+// +build windows,!appengine
package isatty
@@ -76,7 +76,7 @@ func isCygwinPipeName(name string) bool {
}
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
-// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion
+// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
// Windows vista to 10
// see https://stackoverflow.com/a/18792477 for details
diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json
deleted file mode 100644
index 5ae9d96b7..000000000
--- a/vendor/github.com/mattn/go-isatty/renovate.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": [
- "config:base"
- ],
- "postUpdateOptions": [
- "gomodTidy"
- ]
-}
diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
index 1955f2878..9fe803a5e 100644
--- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
+++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md
@@ -1,6 +1,12 @@
-## unreleased
+## 1.4.2
-* Fix regression where `*time.Time` value would be set to empty and not be sent
+* Custom name matchers to support any sort of casing, formatting, etc. for
+ field names. [GH-250]
+* Fix possible panic in ComposeDecodeHookFunc [GH-251]
+
+## 1.4.1
+
+* Fix regression where `*time.Time` value would be set to empty and not be sent
to decode hooks properly [GH-232]
## 1.4.0
diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
index 92e6f76ff..4d4bbc733 100644
--- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
+++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go
@@ -62,7 +62,8 @@ func DecodeHookExec(
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
return func(f reflect.Value, t reflect.Value) (interface{}, error) {
var err error
- var data interface{}
+ data := f.Interface()
+
newFrom := f
for _, f1 := range fs {
data, err = DecodeHookExec(f1, newFrom, t)
diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
index 3643901f5..dcee0f2d6 100644
--- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go
+++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go
@@ -192,7 +192,7 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface
// source and target types.
type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error)
-// DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target
+// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target
// values.
type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error)
@@ -258,6 +258,11 @@ type DecoderConfig struct {
// The tag name that mapstructure reads for field names. This
// defaults to "mapstructure"
TagName string
+
+ // MatchName is the function used to match the map key to the struct
+ // field name or tag. Defaults to `strings.EqualFold`. This can be used
+ // to implement case-sensitive tag values, support snake casing, etc.
+ MatchName func(mapKey, fieldName string) bool
}
// A Decoder takes a raw interface value and turns it into structured
@@ -376,6 +381,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
config.TagName = "mapstructure"
}
+ if config.MatchName == nil {
+ config.MatchName = strings.EqualFold
+ }
+
result := &Decoder{
config: config,
}
@@ -1340,7 +1349,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
continue
}
- if strings.EqualFold(mK, fieldName) {
+ if d.config.MatchName(mK, fieldName) {
rawMapKey = dataValKey
rawMapVal = dataVal.MapIndex(dataValKey)
break
diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go
index e664ade7f..029568a3f 100644
--- a/vendor/github.com/vishvananda/netlink/class_linux.go
+++ b/vendor/github.com/vishvananda/netlink/class_linux.go
@@ -176,6 +176,12 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize())
options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab))
options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab))
+ if htb.Rate >= uint64(1<<32) {
+ options.AddRtAttr(nl.TCA_HTB_RATE64, nl.Uint64Attr(htb.Rate))
+ }
+ if htb.Ceil >= uint64(1<<32) {
+ options.AddRtAttr(nl.TCA_HTB_CEIL64, nl.Uint64Attr(htb.Ceil))
+ }
case "hfsc":
hfsc := class.(*HfscClass)
opt := nl.HfscCopt{}
@@ -306,6 +312,10 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro
htb.Quantum = opt.Quantum
htb.Level = opt.Level
htb.Prio = opt.Prio
+ case nl.TCA_HTB_RATE64:
+ htb.Rate = native.Uint64(datum.Value[0:8])
+ case nl.TCA_HTB_CEIL64:
+ htb.Ceil = native.Uint64(datum.Value[0:8])
}
}
return detailed, nil
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
index 29b3f8ec1..7d57080e8 100644
--- a/vendor/github.com/vishvananda/netlink/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -27,6 +27,18 @@ type DevlinkDevice struct {
Attrs DevlinkDevAttrs
}
+// DevlinkPort represents port and its attributes
+type DevlinkPort struct {
+ BusName string
+ DeviceName string
+ PortIndex uint32
+ PortType uint16
+ NetdeviceName string
+ NetdevIfIndex uint32
+ RdmaDeviceName string
+ PortFlavour uint16
+}
+
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
devices := make([]*DevlinkDevice, 0, len(msgs))
for _, m := range msgs {
@@ -270,3 +282,112 @@ func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error
func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error {
return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode)
}
+
+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)
+ case nl.DEVLINK_ATTR_DEV_NAME:
+ port.DeviceName = string(a.Value)
+ 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)
+ 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)
+ case nl.DEVLINK_ATTR_PORT_FLAVOUR:
+ port.PortFlavour = native.Uint16(a.Value)
+ }
+ }
+ return nil
+}
+
+func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) {
+ ports := make([]*DevlinkPort, 0, len(msgs))
+ for _, m := range msgs {
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ port := &DevlinkPort{}
+ if err = port.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ ports = append(ports, port)
+ }
+ return ports, nil
+}
+
+// DevLinkGetPortList provides a pointer to devlink ports and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) {
+ f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME)
+ if err != nil {
+ return nil, err
+ }
+ msg := &nl.Genlmsg{
+ Command: nl.DEVLINK_CMD_PORT_GET,
+ Version: nl.GENL_DEVLINK_VERSION,
+ }
+ req := h.newNetlinkRequest(int(f.ID),
+ unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP)
+ req.AddData(msg)
+ msgs, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ ports, err := parseDevLinkAllPortList(msgs)
+ if err != nil {
+ return nil, err
+ }
+ return ports, nil
+}
+
+// DevLinkGetPortList provides a pointer to devlink ports and nil error,
+// otherwise returns an error code.
+func DevLinkGetAllPortList() ([]*DevlinkPort, error) {
+ return pkgHandle.DevLinkGetAllPortList()
+}
+
+func parseDevlinkPortMsg(msgs [][]byte) (*DevlinkPort, error) {
+ m := msgs[0]
+ attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:])
+ if err != nil {
+ return nil, err
+ }
+ port := &DevlinkPort{}
+ if err = port.parseAttributes(attrs); err != nil {
+ return nil, err
+ }
+ return port, nil
+}
+
+// DevLinkGetPortByIndexprovides a pointer to devlink device and nil error,
+// otherwise returns an error code.
+func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
+
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_GET, Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+
+ respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ port, err := parseDevlinkPortMsg(respmsg)
+ return port, err
+}
+
+// DevLinkGetPortByIndex provides a pointer to devlink portand nil error,
+// otherwise returns an error code.
+func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
+ return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
+}
diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go
index ef6fabe81..2cd46266c 100644
--- a/vendor/github.com/vishvananda/netlink/filter_linux.go
+++ b/vendor/github.com/vishvananda/netlink/filter_linux.go
@@ -36,6 +36,7 @@ type U32 struct {
ClassId uint32
Divisor uint32 // Divisor MUST be power of 2.
Hash uint32
+ Link uint32
RedirIndex int
Sel *TcU32Sel
Actions []Action
@@ -225,6 +226,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.Hash != 0 {
options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
}
+ if filter.Link != 0 {
+ options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
+ }
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
// backwards compatibility
if filter.RedirIndex != 0 {
@@ -666,6 +670,8 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
u32.Divisor = native.Uint32(datum.Value)
case nl.TCA_U32_HASH:
u32.Hash = native.Uint32(datum.Value)
+ case nl.TCA_U32_LINK:
+ u32.Link = native.Uint32(datum.Value)
}
}
return detailed, nil
diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go
index 26887b759..65356679d 100644
--- a/vendor/github.com/vishvananda/netlink/handle_linux.go
+++ b/vendor/github.com/vishvananda/netlink/handle_linux.go
@@ -21,6 +21,22 @@ type Handle struct {
lookupByDump bool
}
+// SetSocketTimeout configures timeout for default netlink sockets
+func SetSocketTimeout(to time.Duration) error {
+ if to < time.Microsecond {
+ return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
+ }
+
+ nl.SocketTimeoutTv = unix.NsecToTimeval(to.Nanoseconds())
+ return nil
+}
+
+// GetSocketTimeout returns the timeout value used by default netlink sockets
+func GetSocketTimeout() time.Duration {
+ nsec := unix.TimevalToNsec(nl.SocketTimeoutTv)
+ return time.Duration(nsec) * time.Nanosecond
+}
+
// SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
_, ok := h.sockets[nlFamily]
diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
index df341f706..3a6db8137 100644
--- a/vendor/github.com/vishvananda/netlink/handle_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
@@ -237,6 +237,10 @@ func (h *Handle) RouteAdd(route *Route) error {
return ErrNotImplemented
}
+func (h *Handle) RouteAppend(route *Route) error {
+ return ErrNotImplemented
+}
+
func (h *Handle) RouteDel(route *Route) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/inet_diag.go b/vendor/github.com/vishvananda/netlink/inet_diag.go
index 72c1fcb59..bee391a80 100644
--- a/vendor/github.com/vishvananda/netlink/inet_diag.go
+++ b/vendor/github.com/vishvananda/netlink/inet_diag.go
@@ -27,4 +27,5 @@ const (
type InetDiagTCPInfoResp struct {
InetDiagMsg *Socket
TCPInfo *TCPInfo
+ TCPBBRInfo *TCPBBRInfo
}
diff --git a/vendor/github.com/vishvananda/netlink/ipset_linux.go b/vendor/github.com/vishvananda/netlink/ipset_linux.go
index 5487fc1cc..2adc2440a 100644
--- a/vendor/github.com/vishvananda/netlink/ipset_linux.go
+++ b/vendor/github.com/vishvananda/netlink/ipset_linux.go
@@ -23,13 +23,15 @@ type IPSetEntry struct {
// IPSetResult is the result of a dump request for a set
type IPSetResult struct {
- Nfgenmsg *nl.Nfgenmsg
- Protocol uint8
- Revision uint8
- Family uint8
- Flags uint8
- SetName string
- TypeName string
+ Nfgenmsg *nl.Nfgenmsg
+ Protocol uint8
+ ProtocolMinVersion uint8
+ Revision uint8
+ Family uint8
+ Flags uint8
+ SetName string
+ TypeName string
+ Comment string
HashSize uint32
NumEntries uint32
@@ -38,6 +40,7 @@ type IPSetResult struct {
SizeInMemory uint32
CadtFlags uint32
Timeout *uint32
+ LineNo uint32
Entries []IPSetEntry
}
@@ -52,7 +55,7 @@ type IpsetCreateOptions struct {
}
// IpsetProtocol returns the ipset protocol version from the kernel
-func IpsetProtocol() (uint8, error) {
+func IpsetProtocol() (uint8, uint8, error) {
return pkgHandle.IpsetProtocol()
}
@@ -86,20 +89,20 @@ func IpsetAdd(setname string, entry *IPSetEntry) error {
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
}
-// IpsetDele deletes an entry from an existing ipset.
+// IpsetDel deletes an entry from an existing ipset.
func IpsetDel(setname string, entry *IPSetEntry) error {
return pkgHandle.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
}
-func (h *Handle) IpsetProtocol() (uint8, error) {
+func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
req := h.newIpsetRequest(nl.IPSET_CMD_PROTOCOL)
msgs, err := req.Execute(unix.NETLINK_NETFILTER, 0)
if err != nil {
- return 0, err
+ return 0, 0, err
}
-
- return ipsetUnserialize(msgs).Protocol, nil
+ response := ipsetUnserialize(msgs)
+ return response.Protocol, response.ProtocolMinVersion, nil
}
func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOptions) error {
@@ -112,7 +115,7 @@ 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(0)))
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(2))) // 2 == inet
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
@@ -187,6 +190,11 @@ func (h *Handle) IpsetListAll() ([]IPSetResult, error) {
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)))
+
+ if entry.Comment != "" {
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_COMMENT, nl.ZeroTerminated(entry.Comment)))
+ }
+
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
if !entry.Replace {
@@ -197,7 +205,12 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
}
if entry.MAC != nil {
- data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER, entry.MAC))
+ 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()))
}
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
@@ -249,6 +262,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.Protocol = attr.Value[0]
case nl.IPSET_ATTR_SETNAME:
result.SetName = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_COMMENT:
+ result.Comment = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_TYPENAME:
result.TypeName = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_REVISION:
@@ -261,6 +276,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.parseAttrData(attr.Value)
case nl.IPSET_ATTR_ADT | nl.NLA_F_NESTED:
result.parseAttrADT(attr.Value)
+ case nl.IPSET_ATTR_PROTOCOL_MIN:
+ result.ProtocolMinVersion = attr.Value[0]
default:
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -285,6 +302,17 @@ func (result *IPSetResult) parseAttrData(data []byte) {
result.SizeInMemory = attr.Uint32()
case nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER:
result.CadtFlags = attr.Uint32()
+ case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
+ for nested := range nl.ParseAttributes(attr.Value) {
+ 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_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
+ result.LineNo = attr.Uint32()
+ case nl.IPSET_ATTR_COMMENT:
+ result.Comment = nl.BytesToString(attr.Value)
default:
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -316,6 +344,8 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
entry.Packets = &val
case nl.IPSET_ATTR_ETHER:
entry.MAC = net.HardwareAddr(attr.Value)
+ case nl.IPSET_ATTR_IP:
+ entry.IP = net.IP(attr.Value)
case nl.IPSET_ATTR_COMMENT:
entry.Comment = nl.BytesToString(attr.Value)
case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED:
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index e2441bd71..32ca7cd64 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -555,6 +555,27 @@ const (
BOND_ARP_VALIDATE_ALL
)
+var bondArpValidateToString = map[BondArpValidate]string{
+ BOND_ARP_VALIDATE_NONE: "none",
+ BOND_ARP_VALIDATE_ACTIVE: "active",
+ BOND_ARP_VALIDATE_BACKUP: "backup",
+ BOND_ARP_VALIDATE_ALL: "none",
+}
+var StringToBondArpValidateMap = map[string]BondArpValidate{
+ "none": BOND_ARP_VALIDATE_NONE,
+ "active": BOND_ARP_VALIDATE_ACTIVE,
+ "backup": BOND_ARP_VALIDATE_BACKUP,
+ "all": BOND_ARP_VALIDATE_ALL,
+}
+
+func (b BondArpValidate) String() string {
+ s, ok := bondArpValidateToString[b]
+ if !ok {
+ return fmt.Sprintf("BondArpValidate(%d)", b)
+ }
+ return s
+}
+
// BondPrimaryReselect type
type BondPrimaryReselect int
@@ -565,6 +586,25 @@ const (
BOND_PRIMARY_RESELECT_FAILURE
)
+var bondPrimaryReselectToString = map[BondPrimaryReselect]string{
+ BOND_PRIMARY_RESELECT_ALWAYS: "always",
+ BOND_PRIMARY_RESELECT_BETTER: "better",
+ BOND_PRIMARY_RESELECT_FAILURE: "failure",
+}
+var StringToBondPrimaryReselectMap = map[string]BondPrimaryReselect{
+ "always": BOND_PRIMARY_RESELECT_ALWAYS,
+ "better": BOND_PRIMARY_RESELECT_BETTER,
+ "failure": BOND_PRIMARY_RESELECT_FAILURE,
+}
+
+func (b BondPrimaryReselect) String() string {
+ s, ok := bondPrimaryReselectToString[b]
+ if !ok {
+ return fmt.Sprintf("BondPrimaryReselect(%d)", b)
+ }
+ return s
+}
+
// BondArpAllTargets type
type BondArpAllTargets int
@@ -574,6 +614,23 @@ const (
BOND_ARP_ALL_TARGETS_ALL
)
+var bondArpAllTargetsToString = map[BondArpAllTargets]string{
+ BOND_ARP_ALL_TARGETS_ANY: "any",
+ BOND_ARP_ALL_TARGETS_ALL: "all",
+}
+var StringToBondArpAllTargetsMap = map[string]BondArpAllTargets{
+ "any": BOND_ARP_ALL_TARGETS_ANY,
+ "all": BOND_ARP_ALL_TARGETS_ALL,
+}
+
+func (b BondArpAllTargets) String() string {
+ s, ok := bondArpAllTargetsToString[b]
+ if !ok {
+ return fmt.Sprintf("BondArpAllTargets(%d)", b)
+ }
+ return s
+}
+
// BondFailOverMac type
type BondFailOverMac int
@@ -584,6 +641,25 @@ const (
BOND_FAIL_OVER_MAC_FOLLOW
)
+var bondFailOverMacToString = map[BondFailOverMac]string{
+ BOND_FAIL_OVER_MAC_NONE: "none",
+ BOND_FAIL_OVER_MAC_ACTIVE: "active",
+ BOND_FAIL_OVER_MAC_FOLLOW: "follow",
+}
+var StringToBondFailOverMacMap = map[string]BondFailOverMac{
+ "none": BOND_FAIL_OVER_MAC_NONE,
+ "active": BOND_FAIL_OVER_MAC_ACTIVE,
+ "follow": BOND_FAIL_OVER_MAC_FOLLOW,
+}
+
+func (b BondFailOverMac) String() string {
+ s, ok := bondFailOverMacToString[b]
+ if !ok {
+ return fmt.Sprintf("BondFailOverMac(%d)", b)
+ }
+ return s
+}
+
// BondXmitHashPolicy type
type BondXmitHashPolicy int
@@ -675,6 +751,25 @@ const (
BOND_AD_SELECT_COUNT
)
+var bondAdSelectToString = map[BondAdSelect]string{
+ BOND_AD_SELECT_STABLE: "stable",
+ BOND_AD_SELECT_BANDWIDTH: "bandwidth",
+ BOND_AD_SELECT_COUNT: "count",
+}
+var StringToBondAdSelectMap = map[string]BondAdSelect{
+ "stable": BOND_AD_SELECT_STABLE,
+ "bandwidth": BOND_AD_SELECT_BANDWIDTH,
+ "count": BOND_AD_SELECT_COUNT,
+}
+
+func (b BondAdSelect) String() string {
+ s, ok := bondAdSelectToString[b]
+ if !ok {
+ return fmt.Sprintf("BondAdSelect(%d)", b)
+ }
+ return s
+}
+
// BondAdInfo represents ad info for bond
type BondAdInfo struct {
AggregatorId int
@@ -706,7 +801,7 @@ type Bond struct {
AllSlavesActive int
MinLinks int
LpInterval int
- PackersPerSlave int
+ PacketsPerSlave int
LacpRate BondLacpRate
AdSelect BondAdSelect
// looking at iproute tool AdInfo can only be retrived. It can't be set.
@@ -739,7 +834,7 @@ func NewLinkBond(atr LinkAttrs) *Bond {
AllSlavesActive: -1,
MinLinks: -1,
LpInterval: -1,
- PackersPerSlave: -1,
+ PacketsPerSlave: -1,
LacpRate: -1,
AdSelect: -1,
AdActorSysPrio: -1,
@@ -789,8 +884,10 @@ func (bond *Bond) Type() string {
type BondSlaveState uint8
const (
- BondStateActive = iota // Link is active.
- BondStateBackup // Link is backup.
+ //BondStateActive Link is active.
+ BondStateActive BondSlaveState = iota
+ //BondStateBackup Link is backup.
+ BondStateBackup
)
func (s BondSlaveState) String() string {
@@ -804,15 +901,19 @@ func (s BondSlaveState) String() string {
}
}
-// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
+// BondSlaveMiiStatus represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave
// attribute, which contains the status of MII link monitoring
type BondSlaveMiiStatus uint8
const (
- BondLinkUp = iota // link is up and running.
- BondLinkFail // link has just gone down.
- BondLinkDown // link has been down for too long time.
- BondLinkBack // link is going back.
+ //BondLinkUp link is up and running.
+ BondLinkUp BondSlaveMiiStatus = iota
+ //BondLinkFail link has just gone down.
+ BondLinkFail
+ //BondLinkDown link has been down for too long time.
+ BondLinkDown
+ //BondLinkBack link is going back.
+ BondLinkBack
)
func (s BondSlaveMiiStatus) String() string {
@@ -845,6 +946,30 @@ func (b *BondSlave) SlaveType() string {
return "bond"
}
+// 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 {
+ LinkAttrs
+ ID uint32 // vni
+ Remote net.IP
+ Ttl uint8
+ Tos uint8
+ Dport uint16
+ UdpCsum uint8
+ UdpZeroCsum6Tx uint8
+ UdpZeroCsum6Rx uint8
+ Link uint32
+ FlowBased bool
+}
+
+func (geneve *Geneve) Attrs() *LinkAttrs {
+ return &geneve.LinkAttrs
+}
+
+func (geneve *Geneve) Type() string {
+ return "geneve"
+}
+
// Gretap devices must specify LocalIP and RemoteIP on create
type Gretap struct {
LinkAttrs
@@ -1068,6 +1193,58 @@ var StringToIPoIBMode = map[string]IPoIBMode{
"connected": IPOIB_MODE_CONNECTED,
}
+const (
+ CAN_STATE_ERROR_ACTIVE = iota
+ CAN_STATE_ERROR_WARNING
+ CAN_STATE_ERROR_PASSIVE
+ CAN_STATE_BUS_OFF
+ CAN_STATE_STOPPED
+ CAN_STATE_SLEEPING
+)
+
+type Can struct {
+ LinkAttrs
+
+ BitRate uint32
+ SamplePoint uint32
+ TimeQuanta uint32
+ PropagationSegment uint32
+ PhaseSegment1 uint32
+ PhaseSegment2 uint32
+ SyncJumpWidth uint32
+ BitRatePreScaler uint32
+
+ Name string
+ TimeSegment1Min uint32
+ TimeSegment1Max uint32
+ TimeSegment2Min uint32
+ TimeSegment2Max uint32
+ SyncJumpWidthMax uint32
+ BitRatePreScalerMin uint32
+ BitRatePreScalerMax uint32
+ BitRatePreScalerInc uint32
+
+ ClockFrequency uint32
+
+ State uint32
+
+ Mask uint32
+ Flags uint32
+
+ TxError uint16
+ RxError uint16
+
+ RestartMs uint32
+}
+
+func (can *Can) Attrs() *LinkAttrs {
+ return &can.LinkAttrs
+}
+
+func (can *Can) Type() string {
+ return "can"
+}
+
type IPoIB struct {
LinkAttrs
Pkey uint16
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index c02fa63b8..3b959299c 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -34,6 +34,21 @@ const (
TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
)
+var StringToTuntapModeMap = map[string]TuntapMode{
+ "tun": TUNTAP_MODE_TUN,
+ "tap": TUNTAP_MODE_TAP,
+}
+
+func (ttm TuntapMode) String() string {
+ switch ttm {
+ case TUNTAP_MODE_TUN:
+ return "tun"
+ case TUNTAP_MODE_TAP:
+ return "tap"
+ }
+ return "unknown"
+}
+
const (
VF_LINK_STATE_AUTO uint32 = 0
VF_LINK_STATE_ENABLE uint32 = 1
@@ -1046,8 +1061,8 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
if bond.LpInterval >= 0 {
data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
}
- if bond.PackersPerSlave >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave)))
+ if bond.PacketsPerSlave >= 0 {
+ data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave)))
}
if bond.LacpRate >= 0 {
data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
@@ -1404,6 +1419,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
}
+ case *Geneve:
+ addGeneveAttrs(link, linkInfo)
case *Gretap:
addGretapAttrs(link, linkInfo)
case *Iptun:
@@ -1667,6 +1684,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Macvlan{}
case "macvtap":
link = &Macvtap{}
+ case "geneve":
+ link = &Geneve{}
case "gretap":
link = &Gretap{}
case "ip6gretap":
@@ -1693,6 +1712,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Tuntap{}
case "ipoib":
link = &IPoIB{}
+ case "can":
+ link = &Can{}
default:
link = &GenericLink{LinkType: linkType}
}
@@ -1714,6 +1735,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseMacvlanData(link, data)
case "macvtap":
parseMacvtapData(link, data)
+ case "geneve":
+ parseGeneveData(link, data)
case "gretap":
parseGretapData(link, data)
case "ip6gretap":
@@ -1742,6 +1765,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseTuntapData(link, data)
case "ipoib":
parseIPoIBData(link, data)
+ case "can":
+ parseCanData(link, data)
}
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
@@ -2299,7 +2324,7 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
case nl.IFLA_BOND_LP_INTERVAL:
bond.LpInterval = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_PACKETS_PER_SLAVE:
- bond.PackersPerSlave = int(native.Uint32(data[i].Value[0:4]))
+ bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4]))
case nl.IFLA_BOND_AD_LACP_RATE:
bond.LacpRate = BondLacpRate(data[i].Value[0])
case nl.IFLA_BOND_AD_SELECT:
@@ -2448,6 +2473,58 @@ func linkFlags(rawFlags uint32) net.Flags {
return f
}
+func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ if geneve.FlowBased {
+ // In flow based mode, no other attributes need to be configured
+ linkInfo.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, boolAttr(geneve.FlowBased))
+ return
+ }
+
+ if ip := geneve.Remote; ip != nil {
+ if ip4 := ip.To4(); ip4 != nil {
+ data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4())
+ } else {
+ data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip))
+ }
+ }
+
+ if geneve.ID != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID))
+ }
+
+ if geneve.Dport != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport))
+ }
+
+ if geneve.Ttl != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl))
+ }
+
+ if geneve.Tos != 0 {
+ data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
+ }
+}
+
+func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
+ geneve := link.(*Geneve)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_GENEVE_ID:
+ geneve.ID = native.Uint32(datum.Value[0:4])
+ case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6:
+ geneve.Remote = datum.Value
+ case nl.IFLA_GENEVE_PORT:
+ geneve.Dport = ntohs(datum.Value[0:2])
+ case nl.IFLA_GENEVE_TTL:
+ geneve.Ttl = uint8(datum.Value[0])
+ case nl.IFLA_GENEVE_TOS:
+ geneve.Tos = uint8(datum.Value[0])
+ }
+ }
+}
+
func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@@ -3172,6 +3249,54 @@ func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseCanData(link Link, data []syscall.NetlinkRouteAttr) {
+ can := link.(*Can)
+ for _, datum := range data {
+
+ switch datum.Attr.Type {
+ case nl.IFLA_CAN_BITTIMING:
+ can.BitRate = native.Uint32(datum.Value)
+ can.SamplePoint = native.Uint32(datum.Value[4:])
+ can.TimeQuanta = native.Uint32(datum.Value[8:])
+ can.PropagationSegment = native.Uint32(datum.Value[12:])
+ can.PhaseSegment1 = native.Uint32(datum.Value[16:])
+ can.PhaseSegment2 = native.Uint32(datum.Value[20:])
+ can.SyncJumpWidth = native.Uint32(datum.Value[24:])
+ can.BitRatePreScaler = native.Uint32(datum.Value[28:])
+ case nl.IFLA_CAN_BITTIMING_CONST:
+ can.Name = string(datum.Value[:16])
+ can.TimeSegment1Min = native.Uint32(datum.Value[16:])
+ can.TimeSegment1Max = native.Uint32(datum.Value[20:])
+ can.TimeSegment2Min = native.Uint32(datum.Value[24:])
+ can.TimeSegment2Max = native.Uint32(datum.Value[28:])
+ can.SyncJumpWidthMax = native.Uint32(datum.Value[32:])
+ can.BitRatePreScalerMin = native.Uint32(datum.Value[36:])
+ can.BitRatePreScalerMax = native.Uint32(datum.Value[40:])
+ can.BitRatePreScalerInc = native.Uint32(datum.Value[44:])
+ case nl.IFLA_CAN_CLOCK:
+ can.ClockFrequency = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_STATE:
+ can.State = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_CTRLMODE:
+ can.Mask = native.Uint32(datum.Value)
+ can.Flags = native.Uint32(datum.Value[4:])
+ case nl.IFLA_CAN_BERR_COUNTER:
+ can.TxError = native.Uint16(datum.Value)
+ can.RxError = native.Uint16(datum.Value[2:])
+ case nl.IFLA_CAN_RESTART_MS:
+ can.RestartMs = native.Uint32(datum.Value)
+ case nl.IFLA_CAN_DATA_BITTIMING_CONST:
+ case nl.IFLA_CAN_RESTART:
+ case nl.IFLA_CAN_DATA_BITTIMING:
+ case nl.IFLA_CAN_TERMINATION:
+ case nl.IFLA_CAN_TERMINATION_CONST:
+ case nl.IFLA_CAN_BITRATE_CONST:
+ case nl.IFLA_CAN_DATA_BITRATE_CONST:
+ case nl.IFLA_CAN_BITRATE_MAX:
+ }
+ }
+}
+
func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
index db66faaad..aa6155e21 100644
--- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
@@ -10,6 +10,7 @@ const (
const (
DEVLINK_CMD_GET = 1
+ DEVLINK_CMD_PORT_GET = 5
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
)
@@ -17,9 +18,15 @@ const (
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
)
const (
@@ -38,3 +45,19 @@ const (
DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0
DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1
)
+
+const (
+ DEVLINK_PORT_FLAVOUR_PHYSICAL = 0
+ DEVLINK_PORT_FLAVOUR_CPU = 1
+ DEVLINK_PORT_FLAVOUR_DSA = 2
+ DEVLINK_PORT_FLAVOUR_PCI_PF = 3
+ DEVLINK_PORT_FLAVOUR_PCI_VF = 4
+ DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
+)
+
+const (
+ DEVLINK_PORT_TYPE_NOTSET = 0
+ DEVLINK_PORT_TYPE_AUTO = 1
+ DEVLINK_PORT_TYPE_ETH = 2
+ DEVLINK_PORT_TYPE_IB = 3
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index faee2fa03..c72cc436e 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -174,6 +174,22 @@ const (
)
const (
+ IFLA_GENEVE_UNSPEC = iota
+ IFLA_GENEVE_ID // vni
+ IFLA_GENEVE_REMOTE
+ IFLA_GENEVE_TTL
+ IFLA_GENEVE_TOS
+ IFLA_GENEVE_PORT // destination port
+ IFLA_GENEVE_COLLECT_METADATA
+ IFLA_GENEVE_REMOTE6
+ IFLA_GENEVE_UDP_CSUM
+ IFLA_GENEVE_UDP_ZERO_CSUM6_TX
+ IFLA_GENEVE_UDP_ZERO_CSUM6_RX
+ IFLA_GENEVE_LABEL
+ IFLA_GENEVE_MAX = IFLA_GENEVE_LABEL
+)
+
+const (
IFLA_GRE_UNSPEC = iota
IFLA_GRE_LINK
IFLA_GRE_IFLAGS
@@ -673,3 +689,23 @@ const (
IFLA_IPOIB_UMCAST
IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST
)
+
+const (
+ IFLA_CAN_UNSPEC = iota
+ IFLA_CAN_BITTIMING
+ IFLA_CAN_BITTIMING_CONST
+ IFLA_CAN_CLOCK
+ IFLA_CAN_STATE
+ IFLA_CAN_CTRLMODE
+ IFLA_CAN_RESTART_MS
+ IFLA_CAN_RESTART
+ IFLA_CAN_BERR_COUNTER
+ IFLA_CAN_DATA_BITTIMING
+ IFLA_CAN_DATA_BITTIMING_CONST
+ IFLA_CAN_TERMINATION
+ IFLA_CAN_TERMINATION_CONST
+ IFLA_CAN_BITRATE_CONST
+ IFLA_CAN_DATA_BITRATE_CONST
+ IFLA_CAN_BITRATE_MAX
+ IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index cef64b82e..dcd4b9469 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -35,6 +35,9 @@ var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETL
var nextSeqNr uint32
+// Default netlink socket timeout, 60s
+var SocketTimeoutTv = unix.Timeval{Sec: 60, Usec: 0}
+
// GetIPFamily returns the family type of a net.IP.
func GetIPFamily(ip net.IP) int {
if len(ip) <= net.IPv4len {
@@ -426,6 +429,14 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro
if err != nil {
return nil, err
}
+
+ if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil {
+ return nil, err
+ }
+ if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil {
+ return nil, err
+ }
+
defer s.Close()
} else {
s.Lock()
diff --git a/vendor/github.com/vishvananda/netlink/nl/parse_attr.go b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go
index 19eb8f28e..7f49125cf 100644
--- a/vendor/github.com/vishvananda/netlink/nl/parse_attr.go
+++ b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go
@@ -3,6 +3,7 @@ package nl
import (
"encoding/binary"
"fmt"
+ "log"
)
type Attribute struct {
@@ -18,9 +19,20 @@ func ParseAttributes(data []byte) <-chan Attribute {
i := 0
for i+4 < len(data) {
length := int(native.Uint16(data[i : i+2]))
+ attrType := native.Uint16(data[i+2 : i+4])
+
+ if length < 4 {
+ log.Printf("attribute 0x%02x has invalid length of %d bytes", attrType, length)
+ break
+ }
+
+ if len(data) < i+length {
+ log.Printf("attribute 0x%02x of length %d is truncated, only %d bytes remaining", attrType, length, len(data)-i)
+ break
+ }
result <- Attribute{
- Type: native.Uint16(data[i+2 : i+4]),
+ Type: attrType,
Value: data[i+4 : i+length],
}
i += rtaAlignOf(length)
diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go
index 8418569ee..f594c9c21 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc.go
@@ -308,13 +308,15 @@ func (qdisc *Fq) Type() string {
// FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme.
type FqCodel struct {
QdiscAttrs
- Target uint32
- Limit uint32
- Interval uint32
- ECN uint32
- Flows uint32
- Quantum uint32
- // There are some more attributes here, but support for them seems not ubiquitous
+ Target uint32
+ Limit uint32
+ Interval uint32
+ ECN uint32
+ Flows uint32
+ Quantum uint32
+ CEThreshold uint32
+ DropBatchSize uint32
+ MemoryLimit uint32
}
func (fqcodel *FqCodel) String() string {
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index d0e1ca194..edc4b726a 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -250,7 +250,15 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error {
if qdisc.Quantum > 0 {
options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum))))
}
-
+ if qdisc.CEThreshold > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_CE_THRESHOLD, nl.Uint32Attr(qdisc.CEThreshold))
+ }
+ if qdisc.DropBatchSize > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_DROP_BATCH_SIZE, nl.Uint32Attr(qdisc.DropBatchSize))
+ }
+ if qdisc.MemoryLimit > 0 {
+ options.AddRtAttr(nl.TCA_FQ_CODEL_MEMORY_LIMIT, nl.Uint32Attr(qdisc.MemoryLimit))
+ }
case *Fq:
options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing))))
@@ -497,6 +505,12 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
fqCodel.Flows = native.Uint32(datum.Value)
case nl.TCA_FQ_CODEL_QUANTUM:
fqCodel.Quantum = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_CE_THRESHOLD:
+ fqCodel.CEThreshold = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_DROP_BATCH_SIZE:
+ fqCodel.DropBatchSize = native.Uint32(datum.Value)
+ case nl.TCA_FQ_CODEL_MEMORY_LIMIT:
+ fqCodel.MemoryLimit = native.Uint32(datum.Value)
}
}
return nil
diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go
index b16254174..845f41808 100644
--- a/vendor/github.com/vishvananda/netlink/route.go
+++ b/vendor/github.com/vishvananda/netlink/route.go
@@ -27,6 +27,9 @@ type Encap interface {
Equal(Encap) bool
}
+//Protocol describe what was the originator of the route
+type RouteProtocol int
+
// Route represents a netlink route.
type Route struct {
LinkIndex int
@@ -36,7 +39,7 @@ type Route struct {
Src net.IP
Gw net.IP
MultiPath []*NexthopInfo
- Protocol int
+ Protocol RouteProtocol
Priority int
Table int
Type int
@@ -45,6 +48,7 @@ type Route struct {
MPLSDst *int
NewDst Destination
Encap Encap
+ Via Destination
MTU int
Window int
Rtt int
@@ -79,6 +83,9 @@ func (r Route) String() string {
if r.Encap != nil {
elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap))
}
+ if r.Via != nil {
+ elems = append(elems, fmt.Sprintf("Via: %s", r.Via))
+ }
elems = append(elems, fmt.Sprintf("Src: %s", r.Src))
if len(r.MultiPath) > 0 {
elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath))
@@ -107,6 +114,7 @@ func (r Route) Equal(x Route) bool {
r.Flags == x.Flags &&
(r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) &&
(r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) &&
+ (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) &&
(r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap)))
}
@@ -136,6 +144,7 @@ type NexthopInfo struct {
Flags int
NewDst Destination
Encap Encap
+ Via Destination
}
func (n *NexthopInfo) String() string {
@@ -147,6 +156,9 @@ func (n *NexthopInfo) String() string {
if n.Encap != nil {
elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap))
}
+ if n.Via != nil {
+ elems = append(elems, fmt.Sprintf("Via: %s", n.Via))
+ }
elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1))
elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw))
elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags()))
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 4e778a417..32641cb0d 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -1,8 +1,11 @@
package netlink
import (
+ "bytes"
+ "encoding/binary"
"fmt"
"net"
+ "strconv"
"strings"
"syscall"
@@ -21,6 +24,23 @@ const (
SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE
)
+func (s Scope) String() string {
+ switch s {
+ case SCOPE_UNIVERSE:
+ return "universe"
+ case SCOPE_SITE:
+ return "site"
+ case SCOPE_LINK:
+ return "link"
+ case SCOPE_HOST:
+ return "host"
+ case SCOPE_NOWHERE:
+ return "nowhere"
+ default:
+ return "unknown"
+ }
+}
+
const (
RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota)
RT_FILTER_SCOPE
@@ -446,6 +466,62 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
return true
}
+type Via struct {
+ AddrFamily int
+ Addr net.IP
+}
+
+func (v *Via) Equal(x Destination) bool {
+ o, ok := x.(*Via)
+ if !ok {
+ return false
+ }
+ if v.AddrFamily == x.Family() && v.Addr.Equal(o.Addr) {
+ return true
+ }
+ return false
+}
+
+func (v *Via) String() string {
+ return fmt.Sprintf("Family: %d, Address: %s", v.AddrFamily, v.Addr.String())
+}
+
+func (v *Via) Family() int {
+ return v.AddrFamily
+}
+
+func (v *Via) Encode() ([]byte, error) {
+ buf := &bytes.Buffer{}
+ err := binary.Write(buf, native, uint16(v.AddrFamily))
+ if err != nil {
+ return nil, err
+ }
+ err = binary.Write(buf, native, v.Addr)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+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))
+ }
+ v.AddrFamily = int(native.Uint16(b[0:2]))
+ if v.AddrFamily == nl.FAMILY_V4 {
+ v.Addr = net.IP(b[2:6])
+ return nil
+ } else if v.AddrFamily == nl.FAMILY_V6 {
+ if len(b) < 18 {
+ return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
+ }
+ v.Addr = net.IP(b[2:])
+ return nil
+ }
+ return fmt.Errorf("decoding failed: address family %d unknown", v.AddrFamily)
+}
+
// RouteAdd will add a route to the system.
// Equivalent to: `ip route add $route`
func RouteAdd(route *Route) error {
@@ -460,6 +536,32 @@ func (h *Handle) RouteAdd(route *Route) error {
return h.routeHandle(route, req, nl.NewRtMsg())
}
+// RouteAppend will append a route to the system.
+// Equivalent to: `ip route append $route`
+func RouteAppend(route *Route) error {
+ return pkgHandle.RouteAppend(route)
+}
+
+// RouteAppend will append a route to the system.
+// Equivalent to: `ip route append $route`
+func (h *Handle) RouteAppend(route *Route) error {
+ flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK
+ req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
+ return h.routeHandle(route, req, nl.NewRtMsg())
+}
+
+// RouteAddEcmp will add a route to the system.
+func RouteAddEcmp(route *Route) error {
+ 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())
+}
+
// RouteReplace will add a route to the system.
// Equivalent to: `ip route replace $route`
func RouteReplace(route *Route) error {
@@ -567,6 +669,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData))
}
+ if route.Via != nil {
+ buf, err := route.Via.Encode()
+ if err != nil {
+ return fmt.Errorf("failed to encode RTA_VIA: %v", err)
+ }
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf))
+ }
+
if len(route.MultiPath) > 0 {
buf := []byte{}
for _, nh := range route.MultiPath {
@@ -609,6 +719,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
}
children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf))
}
+ if nh.Via != nil {
+ buf, err := nh.Via.Encode()
+ if err != nil {
+ return err
+ }
+ children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf))
+ }
rtnh.Children = children
buf = append(buf, rtnh.Serialize()...)
}
@@ -834,7 +951,7 @@ func deserializeRoute(m []byte) (Route, error) {
}
route := Route{
Scope: Scope(msg.Scope),
- Protocol: int(msg.Protocol),
+ Protocol: RouteProtocol(int(msg.Protocol)),
Table: int(msg.Table),
Type: int(msg.Type),
Tos: int(msg.Tos),
@@ -907,6 +1024,12 @@ func deserializeRoute(m []byte) (Route, error) {
encapType = attr
case unix.RTA_ENCAP:
encap = attr
+ case unix.RTA_VIA:
+ d := &Via{}
+ if err := d.Decode(attr.Value); err != nil {
+ return nil, nil, err
+ }
+ info.Via = d
}
}
@@ -944,6 +1067,12 @@ func deserializeRoute(m []byte) (Route, error) {
return route, err
}
route.NewDst = d
+ case unix.RTA_VIA:
+ v := &Via{}
+ if err := v.Decode(attr.Value); err != nil {
+ return route, err
+ }
+ route.Via = v
case unix.RTA_ENCAP_TYPE:
encapType = attr
case unix.RTA_ENCAP:
@@ -1022,6 +1151,7 @@ func deserializeRoute(m []byte) (Route, error) {
// RouteGetWithOptions
type RouteGetOptions struct {
VrfName string
+ SrcAddr net.IP
}
// RouteGetWithOptions gets a route to a specific destination from the host system.
@@ -1053,23 +1183,40 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
msg := &nl.RtMsg{}
msg.Family = uint8(family)
msg.Dst_len = bitlen
+ if options != nil && options.SrcAddr != nil {
+ msg.Src_len = bitlen
+ }
+ msg.Flags = unix.RTM_F_LOOKUP_TABLE
req.AddData(msg)
rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData)
req.AddData(rtaDst)
if options != nil {
- link, err := LinkByName(options.VrfName)
- if err != nil {
- return nil, err
+ if options.VrfName != "" {
+ link, err := LinkByName(options.VrfName)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ b = make([]byte, 4)
+ native = nl.NativeEndian()
+ )
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
- native.PutUint32(b, uint32(link.Attrs().Index))
- req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
+ if options.SrcAddr != nil {
+ var srcAddr []byte
+ if family == FAMILY_V4 {
+ srcAddr = options.SrcAddr.To4()
+ } else {
+ srcAddr = options.SrcAddr.To16()
+ }
+
+ req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
+ }
}
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)
@@ -1190,3 +1337,54 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
return nil
}
+
+func (p RouteProtocol) String() string {
+ switch int(p) {
+ case unix.RTPROT_BABEL:
+ return "babel"
+ case unix.RTPROT_BGP:
+ return "bgp"
+ case unix.RTPROT_BIRD:
+ return "bird"
+ case unix.RTPROT_BOOT:
+ return "boot"
+ case unix.RTPROT_DHCP:
+ return "dhcp"
+ case unix.RTPROT_DNROUTED:
+ return "dnrouted"
+ case unix.RTPROT_EIGRP:
+ return "eigrp"
+ case unix.RTPROT_GATED:
+ return "gated"
+ case unix.RTPROT_ISIS:
+ return "isis"
+ //case unix.RTPROT_KEEPALIVED:
+ // return "keepalived"
+ case unix.RTPROT_KERNEL:
+ return "kernel"
+ case unix.RTPROT_MROUTED:
+ return "mrouted"
+ case unix.RTPROT_MRT:
+ return "mrt"
+ case unix.RTPROT_NTK:
+ return "ntk"
+ case unix.RTPROT_OSPF:
+ return "ospf"
+ case unix.RTPROT_RA:
+ return "ra"
+ case unix.RTPROT_REDIRECT:
+ return "redirect"
+ case unix.RTPROT_RIP:
+ return "rip"
+ case unix.RTPROT_STATIC:
+ return "static"
+ case unix.RTPROT_UNSPEC:
+ return "unspec"
+ case unix.RTPROT_XORP:
+ return "xorp"
+ case unix.RTPROT_ZEBRA:
+ return "zebra"
+ default:
+ return strconv.Itoa(int(p))
+ }
+}
diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go
index 2701862b4..db7372689 100644
--- a/vendor/github.com/vishvananda/netlink/route_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/route_unspecified.go
@@ -2,6 +2,8 @@
package netlink
+import "strconv"
+
func (r *Route) ListFlags() []string {
return []string{}
}
@@ -9,3 +11,11 @@ func (r *Route) ListFlags() []string {
func (n *NexthopInfo) ListFlags() []string {
return []string{}
}
+
+func (s Scope) String() string {
+ return "unknown"
+}
+
+func (p RouteProtocol) String() string {
+ return strconv.Itoa(int(p))
+}
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index e4e7f7ac3..9b0f4a081 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -184,7 +184,7 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
req.AddData(&socketRequest{
Family: family,
Protocol: unix.IPPROTO_TCP,
- Ext: INET_DIAG_INFO,
+ Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)),
States: uint32(0xfff), // All TCP states
})
s.Send(req)
@@ -220,19 +220,42 @@ loop:
if err != nil {
return nil, err
}
- var tcpInfo *TCPInfo
- for _, a := range attrs {
- if a.Attr.Type == INET_DIAG_INFO {
- tcpInfo = &TCPInfo{}
- if err := tcpInfo.deserialize(a.Value); err != nil {
- return nil, err
- }
- break
- }
+
+ res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
+ if err != nil {
+ return nil, err
}
- r := &InetDiagTCPInfoResp{InetDiagMsg: sockInfo, TCPInfo: tcpInfo}
- result = append(result, r)
+
+ result = append(result, res)
}
}
return result, nil
}
+
+func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
+ var tcpInfo *TCPInfo
+ var tcpBBRInfo *TCPBBRInfo
+ for _, a := range attrs {
+ if a.Attr.Type == INET_DIAG_INFO {
+ tcpInfo = &TCPInfo{}
+ if err := tcpInfo.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ continue
+ }
+
+ if a.Attr.Type == INET_DIAG_BBRINFO {
+ tcpBBRInfo = &TCPBBRInfo{}
+ if err := tcpBBRInfo.deserialize(a.Value); err != nil {
+ return nil, err
+ }
+ continue
+ }
+ }
+
+ return &InetDiagTCPInfoResp{
+ InetDiagMsg: sockInfo,
+ TCPInfo: tcpInfo,
+ TCPBBRInfo: tcpBBRInfo,
+ }, nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/tcp.go b/vendor/github.com/vishvananda/netlink/tcp.go
index 4a42ee5a6..23ca014d4 100644
--- a/vendor/github.com/vishvananda/netlink/tcp.go
+++ b/vendor/github.com/vishvananda/netlink/tcp.go
@@ -16,3 +16,69 @@ const (
TCP_NEW_SYN_REC
TCP_MAX_STATES
)
+
+type TCPInfo struct {
+ State uint8
+ Ca_state uint8
+ Retransmits uint8
+ Probes uint8
+ Backoff uint8
+ Options uint8
+ Snd_wscale uint8 // no uint4
+ Rcv_wscale uint8
+ Delivery_rate_app_limited uint8
+ Fastopen_client_fail uint8
+ Rto uint32
+ Ato uint32
+ Snd_mss uint32
+ Rcv_mss uint32
+ Unacked uint32
+ Sacked uint32
+ Lost uint32
+ Retrans uint32
+ Fackets uint32
+ Last_data_sent uint32
+ Last_ack_sent uint32
+ Last_data_recv uint32
+ Last_ack_recv uint32
+ Pmtu uint32
+ Rcv_ssthresh uint32
+ Rtt uint32
+ Rttvar uint32
+ Snd_ssthresh uint32
+ Snd_cwnd uint32
+ Advmss uint32
+ Reordering uint32
+ Rcv_rtt uint32
+ Rcv_space uint32
+ Total_retrans uint32
+ Pacing_rate uint64
+ Max_pacing_rate uint64
+ Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
+ Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
+ Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */
+ Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */
+ Notsent_bytes uint32
+ Min_rtt uint32
+ Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */
+ Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */
+ Delivery_rate uint64
+ Busy_time uint64 /* Time (usec) busy sending data */
+ Rwnd_limited uint64 /* Time (usec) limited by receive window */
+ Sndbuf_limited uint64 /* Time (usec) limited by send buffer */
+ Delivered uint32
+ Delivered_ce uint32
+ Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
+ Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */
+ Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */
+ Reord_seen uint32 /* reordering events seen */
+ Rcv_ooopack uint32 /* Out-of-order packets received */
+ Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */
+}
+
+type TCPBBRInfo struct {
+ BBRBW uint64
+ BBRMinRTT uint32
+ BBRPacingGain uint32
+ BBRCwndGain uint32
+}
diff --git a/vendor/github.com/vishvananda/netlink/tcp_linux.go b/vendor/github.com/vishvananda/netlink/tcp_linux.go
index 741ea1655..293858738 100644
--- a/vendor/github.com/vishvananda/netlink/tcp_linux.go
+++ b/vendor/github.com/vishvananda/netlink/tcp_linux.go
@@ -2,67 +2,13 @@ package netlink
import (
"bytes"
+ "errors"
"io"
)
-type TCPInfo struct {
- State uint8
- Ca_state uint8
- Retransmits uint8
- Probes uint8
- Backoff uint8
- Options uint8
- Snd_wscale uint8 // no uint4
- Rcv_wscale uint8
- Delivery_rate_app_limited uint8
- Fastopen_client_fail uint8
- Rto uint32
- Ato uint32
- Snd_mss uint32
- Rcv_mss uint32
- Unacked uint32
- Sacked uint32
- Lost uint32
- Retrans uint32
- Fackets uint32
- Last_data_sent uint32
- Last_ack_sent uint32
- Last_data_recv uint32
- Last_ack_recv uint32
- Pmtu uint32
- Rcv_ssthresh uint32
- Rtt uint32
- Rttvar uint32
- Snd_ssthresh uint32
- Snd_cwnd uint32
- Advmss uint32
- Reordering uint32
- Rcv_rtt uint32
- Rcv_space uint32
- Total_retrans uint32
- Pacing_rate uint64
- Max_pacing_rate uint64
- Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
- Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
- Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */
- Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */
- Notsent_bytes uint32
- Min_rtt uint32
- Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */
- Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */
- Delivery_rate uint64
- Busy_time uint64 /* Time (usec) busy sending data */
- Rwnd_limited uint64 /* Time (usec) limited by receive window */
- Sndbuf_limited uint64 /* Time (usec) limited by send buffer */
- Delivered uint32
- Delivered_ce uint32
- Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
- Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */
- Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */
- Reord_seen uint32 /* reordering events seen */
- Rcv_ooopack uint32 /* Out-of-order packets received */
- Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */
-}
+const (
+ tcpBBRInfoLen = 20
+)
func checkDeserErr(err error) error {
if err == io.EOF {
@@ -391,3 +337,17 @@ func (t *TCPInfo) deserialize(b []byte) error {
t.Snd_wnd = native.Uint32(next)
return nil
}
+
+func (t *TCPBBRInfo) deserialize(b []byte) error {
+ if len(b) != tcpBBRInfoLen {
+ return errors.New("Invalid length")
+ }
+
+ rb := bytes.NewBuffer(b)
+ t.BBRBW = native.Uint64(rb.Next(8))
+ t.BBRMinRTT = native.Uint32(rb.Next(4))
+ t.BBRPacingGain = native.Uint32(rb.Next(4))
+ t.BBRCwndGain = native.Uint32(rb.Next(4))
+
+ return nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
index 6219d2772..b7532b092 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy.go
@@ -58,12 +58,13 @@ func (a PolicyAction) String() string {
// policy. These rules are matched with XfrmState to determine encryption
// and authentication algorithms.
type XfrmPolicyTmpl struct {
- Dst net.IP
- Src net.IP
- Proto Proto
- Mode Mode
- Spi int
- Reqid int
+ Dst net.IP
+ Src net.IP
+ Proto Proto
+ Mode Mode
+ Spi int
+ Reqid int
+ Optional int
}
func (t XfrmPolicyTmpl) String() string {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
index a4e132ef5..694bd74e6 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go
@@ -79,6 +79,7 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error {
userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi))
userTmpl.Mode = uint8(tmpl.Mode)
userTmpl.Reqid = uint32(tmpl.Reqid)
+ userTmpl.Optional = uint8(tmpl.Optional)
userTmpl.Aalgos = ^uint32(0)
userTmpl.Ealgos = ^uint32(0)
userTmpl.Calgos = ^uint32(0)
@@ -247,6 +248,7 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) {
resTmpl.Mode = Mode(tmpl.Mode)
resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi))
resTmpl.Reqid = int(tmpl.Reqid)
+ resTmpl.Optional = int(tmpl.Optional)
policy.Tmpls = append(policy.Tmpls, resTmpl)
}
case nl.XFRMA_MARK:
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go
index 483d8934a..19df82c76 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state.go
@@ -94,7 +94,7 @@ type XfrmState struct {
Limits XfrmStateLimits
Statistics XfrmStateStats
Mark *XfrmMark
- OutputMark int
+ OutputMark *XfrmMark
Ifid int
Auth *XfrmStateAlgo
Crypt *XfrmStateAlgo
@@ -104,7 +104,7 @@ type XfrmState struct {
}
func (sa XfrmState) String() string {
- return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
+ return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t",
sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN)
}
func (sa XfrmState) Print(stats bool) string {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
index 66c99423c..5b1b6c31a 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -158,9 +158,13 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow))
req.AddData(out)
}
- if state.OutputMark != 0 {
- out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark)))
+ if state.OutputMark != nil {
+ out := nl.NewRtAttr(nl.XFRMA_SET_MARK, nl.Uint32Attr(state.OutputMark.Value))
req.AddData(out)
+ if state.OutputMark.Mask != 0 {
+ out = nl.NewRtAttr(nl.XFRMA_SET_MARK_MASK, nl.Uint32Attr(state.OutputMark.Mask))
+ req.AddData(out)
+ }
}
ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid)))
@@ -377,8 +381,19 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) {
state.Mark = new(XfrmMark)
state.Mark.Value = mark.Value
state.Mark.Mask = mark.Mask
- case nl.XFRMA_OUTPUT_MARK:
- state.OutputMark = int(native.Uint32(attr.Value))
+ case nl.XFRMA_SET_MARK:
+ if state.OutputMark == nil {
+ state.OutputMark = new(XfrmMark)
+ }
+ state.OutputMark.Value = native.Uint32(attr.Value)
+ case nl.XFRMA_SET_MARK_MASK:
+ if state.OutputMark == nil {
+ state.OutputMark = new(XfrmMark)
+ }
+ state.OutputMark.Mask = native.Uint32(attr.Value)
+ if state.OutputMark.Mask == 0xffffffff {
+ state.OutputMark.Mask = 0
+ }
case nl.XFRMA_IF_ID:
state.Ifid = int(native.Uint32(attr.Value))
}
diff --git a/vendor/github.com/vishvananda/netns/README.md b/vendor/github.com/vishvananda/netns/README.md
index 6b45cfb89..1fdb2d3e4 100644
--- a/vendor/github.com/vishvananda/netns/README.md
+++ b/vendor/github.com/vishvananda/netns/README.md
@@ -48,3 +48,14 @@ func main() {
}
```
+
+## NOTE
+
+The library can be safely used only with Go >= 1.10 due to [golang/go#20676](https://github.com/golang/go/issues/20676).
+
+After locking a goroutine to its current OS thread with `runtime.LockOSThread()`
+and changing its network namespace, any new subsequent goroutine won't be
+scheduled on that thread while it's locked. Therefore, the new goroutine
+will run in a different namespace leading to unexpected results.
+
+See [here](https://www.weave.works/blog/linux-namespaces-golang-followup) for more details.
diff --git a/vendor/github.com/vishvananda/netns/netns_linux.go b/vendor/github.com/vishvananda/netns/netns_linux.go
index c76acd087..36e64906b 100644
--- a/vendor/github.com/vishvananda/netns/netns_linux.go
+++ b/vendor/github.com/vishvananda/netns/netns_linux.go
@@ -1,4 +1,4 @@
-// +build linux
+// +build linux,go1.10
package netns
@@ -218,12 +218,18 @@ func getPidForContainer(id string) (int, error) {
filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"),
// Even more recent docker versions under cgroup/systemd/docker/<id>/
filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"),
- // Kubernetes with docker and CNI is even more different
+ // Kubernetes with docker and CNI is even more different. Works for BestEffort and Burstable QoS
filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "*", "pod*", id, "tasks"),
- // Another flavor of containers location in recent kubernetes 1.11+
- filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
- // When runs inside of a container with recent kubernetes 1.11+
- filepath.Join(cgroupRoot, "kubepods.slice", "kubepods-besteffort.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, "..", "systemd", "kubepods", "pod*", id, "tasks"),
+ // Another flavor of containers location in recent kubernetes 1.11+. Works for BestEffort and Burstable QoS
+ filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, cgroupThis, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"),
+ // When runs inside of a container with recent kubernetes 1.11+. Works for BestEffort and Burstable QoS
+ filepath.Join(cgroupRoot, "kubepods.slice", "*.slice", "*", "docker-"+id+".scope", "tasks"),
+ // Same as above but for Guaranteed QoS
+ filepath.Join(cgroupRoot, "kubepods.slice", "*", "docker-"+id+".scope", "tasks"),
}
var filename string
diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE b/vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of Google Inc. 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
+OWNER 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/k8s.io/apimachinery/third_party/forked/golang/PATENTS b/vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS
new file mode 100644
index 000000000..733099041
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 324487b7c..1927f8285 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -45,7 +45,7 @@ github.com/blang/semver
github.com/buger/goterm
# github.com/cespare/xxhash/v2 v2.1.1
github.com/cespare/xxhash/v2
-# github.com/checkpoint-restore/checkpointctl v0.0.0-20210301084134-a2024f5584e7
+# github.com/checkpoint-restore/checkpointctl v0.0.0-20210922093614-c31748bec9f2
github.com/checkpoint-restore/checkpointctl/lib
# github.com/checkpoint-restore/go-criu/v5 v5.1.0
github.com/checkpoint-restore/go-criu/v5
@@ -66,15 +66,18 @@ github.com/containerd/containerd/sys
# github.com/containerd/stargz-snapshotter/estargz v0.8.0
github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil
-# github.com/containernetworking/cni v0.8.1
+# github.com/containernetworking/cni v1.0.1
github.com/containernetworking/cni/libcni
github.com/containernetworking/cni/pkg/invoke
github.com/containernetworking/cni/pkg/types
github.com/containernetworking/cni/pkg/types/020
-github.com/containernetworking/cni/pkg/types/current
+github.com/containernetworking/cni/pkg/types/040
+github.com/containernetworking/cni/pkg/types/100
+github.com/containernetworking/cni/pkg/types/create
+github.com/containernetworking/cni/pkg/types/internal
github.com/containernetworking/cni/pkg/utils
github.com/containernetworking/cni/pkg/version
-# github.com/containernetworking/plugins v0.9.1
+# github.com/containernetworking/plugins v1.0.1
github.com/containernetworking/plugins/pkg/ns
# github.com/containers/buildah v1.23.0
github.com/containers/buildah
@@ -94,7 +97,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.44.1-0.20210914173811-fcaa2e0de285
+# github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
github.com/containers/common/pkg/apparmor
@@ -191,7 +194,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.6.0
+# github.com/containers/psgo v1.7.1
github.com/containers/psgo
github.com/containers/psgo/internal/capabilities
github.com/containers/psgo/internal/cgroups
@@ -199,7 +202,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.36.0
+# github.com/containers/storage v1.36.1-0.20210929132900-162a0bf730ce
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -402,7 +405,7 @@ github.com/json-iterator/go
# github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a
github.com/juju/ansiterm
github.com/juju/ansiterm/tabwriter
-# github.com/klauspost/compress v1.13.5
+# github.com/klauspost/compress v1.13.6
github.com/klauspost/compress
github.com/klauspost/compress/flate
github.com/klauspost/compress/fse
@@ -420,7 +423,7 @@ github.com/manifoldco/promptui/list
github.com/manifoldco/promptui/screenbuf
# github.com/mattn/go-colorable v0.1.8
github.com/mattn/go-colorable
-# github.com/mattn/go-isatty v0.0.12
+# github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-isatty
# github.com/mattn/go-runewidth v0.0.13
github.com/mattn/go-runewidth
@@ -432,7 +435,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
github.com/miekg/pkcs11
# github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
github.com/mistifyio/go-zfs
-# github.com/mitchellh/mapstructure v1.4.1
+# github.com/mitchellh/mapstructure v1.4.2
github.com/mitchellh/mapstructure
# github.com/moby/sys/mount v0.2.0
github.com/moby/sys/mount
@@ -614,10 +617,10 @@ 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.20201029203352-d40f9887b852
+# github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
github.com/vishvananda/netlink
github.com/vishvananda/netlink/nl
-# github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae
+# github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
github.com/vishvananda/netns
# github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b
github.com/xeipuuv/gojsonpointer
@@ -797,10 +800,10 @@ gopkg.in/tomb.v1
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gopkg.in/yaml.v3
-# k8s.io/api v0.22.1
+# k8s.io/api v0.22.2
k8s.io/api/apps/v1
k8s.io/api/core/v1
-# k8s.io/apimachinery v0.22.1
+# k8s.io/apimachinery v0.22.2
k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/apis/meta/v1
k8s.io/apimachinery/pkg/conversion