summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml31
-rwxr-xr-xAPI.md2
-rw-r--r--Makefile2
-rw-r--r--RELEASE_NOTES.md18
-rw-r--r--changelog.txt48
-rw-r--r--cmd/podman/cliconfig/config.go14
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/network.go31
-rw-r--r--cmd/podman/network_inspect.go48
-rw-r--r--cmd/podman/network_list.go53
-rw-r--r--cmd/podman/network_rm.go48
-rw-r--r--cmd/podman/pull.go4
-rw-r--r--cmd/podman/shared/container.go2
-rw-r--r--cmd/podman/shared/create.go8
-rw-r--r--cmd/podman/shared/intermediate.go1
-rw-r--r--cmd/podman/shared/intermediate_varlink.go2
-rw-r--r--cmd/podman/sign.go3
-rw-r--r--cmd/podman/varlink/io.podman.varlink1
-rw-r--r--commands.md4
-rw-r--r--completions/bash/podman73
-rwxr-xr-xcontrib/cirrus/integration_test.sh9
-rwxr-xr-xcontrib/cirrus/networking.sh17
-rw-r--r--contrib/cirrus/required_host_ports.txt11
-rwxr-xr-xcontrib/cirrus/setup_environment.sh5
-rw-r--r--contrib/perftest/main.go2
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--docs/podman-create.1.md11
-rw-r--r--docs/podman-network-inspect.1.md50
-rw-r--r--docs/podman-network-ls.1.md43
-rw-r--r--docs/podman-network-rm.1.md25
-rw-r--r--docs/podman-network.1.md21
-rw-r--r--docs/podman-run.1.md11
-rw-r--r--docs/podman.1.md1
-rw-r--r--libpod/image/image.go6
-rw-r--r--libpod/image/image_test.go11
-rw-r--r--libpod/runtime_pod_infra_linux.go6
-rw-r--r--pkg/adapter/checkpoint_restore.go3
-rw-r--r--pkg/adapter/network.go147
-rw-r--r--pkg/adapter/pods.go3
-rw-r--r--pkg/adapter/runtime.go11
-rw-r--r--pkg/adapter/runtime_remote.go3
-rw-r--r--pkg/network/config.go4
-rw-r--r--pkg/network/network.go26
-rw-r--r--pkg/spec/storage.go4
-rw-r--r--pkg/util/mountOpts.go3
-rw-r--r--pkg/util/utils.go29
-rw-r--r--pkg/varlinkapi/images.go2
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/create_test.go10
-rw-r--r--test/e2e/network_test.go158
-rw-r--r--test/e2e/pause_test.go12
-rw-r--r--test/e2e/run_cpu_test.go110
-rw-r--r--test/e2e/run_memory_test.go38
-rw-r--r--test/e2e/run_test.go90
-rw-r--r--version/version.go2
55 files changed, 1197 insertions, 88 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 66bb7d4ce..5a9dbcb54 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -93,8 +93,8 @@ gating_task:
timeout_in: 20m
- networking_script: # Don't bother going further if something is down
- - 'while read host port; do nc -zv -w 13 $host $port || exit 1; done < ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/required_host_ports.txt'
+ # Don't bother going further if something is down
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
gate_script:
# N/B: entrypoint.sh resets $GOSRC (same as make clean)
@@ -331,6 +331,7 @@ testing_task:
TEST_REMOTE_CLIENT: true
TEST_REMOTE_CLIENT: false
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
@@ -348,7 +349,7 @@ testing_task:
audit_log_script: '$SCRIPT_BASE/logcollector.sh audit'
journal_script: '$SCRIPT_BASE/logcollector.sh journal'
-# Test crun on last Fedora
+# Test crun only on latest Fedora
testing_crun_task:
depends_on:
@@ -361,20 +362,15 @@ testing_crun_task:
# Only test build cache-images, if that's what's requested
only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\*\*\*\s*CIRRUS:\s*TEST\s*IMAGES\s*\*\*\*.*'
- gce_instance:
- matrix:
- # Images are generated separately, from build_images_task (below)
- image_name: "${FEDORA_CACHE_IMAGE_NAME}"
-
timeout_in: 120m
env:
ADD_SECOND_PARTITION: true
OCI_RUNTIME: "/usr/bin/crun"
- matrix:
- TEST_REMOTE_CLIENT: false
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
+ install_crun_script: 'dnf install -y crun'
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
@@ -385,11 +381,8 @@ testing_crun_task:
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
- always: &crunstandardlogs
- ginkgo_node_logs_script: '$SCRIPT_BASE/logcollector.sh ginkgo'
- df_script: '$SCRIPT_BASE/logcollector.sh df'
- audit_log_script: '$SCRIPT_BASE/logcollector.sh audit'
- journal_script: '$SCRIPT_BASE/logcollector.sh journal'
+ always:
+ <<: *standardlogs
# This task executes tests under unique environments/conditions
@@ -413,6 +406,7 @@ special_testing_rootless_task:
timeout_in: 60m
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
@@ -441,6 +435,7 @@ special_testing_in_podman_task:
timeout_in: 60m
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
@@ -467,6 +462,7 @@ special_testing_cross_task:
timeout_in: 20m
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
cache_release_archive_script: '$SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}'
@@ -494,6 +490,7 @@ special_testing_cgroupv2_task:
timeout_in: 20m
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
@@ -529,7 +526,8 @@ test_build_cache_images_task:
- compute
- devstorage.full_control
- environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
+ setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
build_vm_images_script: '$SCRIPT_BASE/build_vm_images.sh |& ${TIMESTAMP}'
df_script: '${DFCMD}'
journalctl_b_script: 'journalctl -b'
@@ -568,6 +566,7 @@ verify_test_built_images_task:
PACKER_BUILDER_NAME: "xfedora-30"
PACKER_BUILDER_NAME: "ubuntu-18"
+ networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
# Verify expectations once per image
check_image_script: >-
diff --git a/API.md b/API.md
index 336902616..4afa18b45 100755
--- a/API.md
+++ b/API.md
@@ -1503,6 +1503,8 @@ publish [?[]string](#?[]string)
publishAll [?bool](#?bool)
+pull [?string](#?string)
+
quiet [?bool](#?bool)
readonly [?bool](#?bool)
diff --git a/Makefile b/Makefile
index 4138586af..c4b66e261 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ export GO111MODULE=off
GO ?= go
DESTDIR ?=
-EPOCH_TEST_COMMIT ?= bb80586e275fe0d3f47700ec54c9718a28b1e59c
+EPOCH_TEST_COMMIT ?= b9a176bea94b8e3a97a70dd7cd599f1a057777b0
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index f55fd9b18..3cfd8ed86 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,23 @@
# Release Notes
+## 1.5.1
+### Features
+- The hostname of pods is now set to the pod's name
+
+### Bugfixes
+- Fixed a bug where `podman run` and `podman create` did not honor the `--authfile` option ([#3730](https://github.com/containers/libpod/issues/3730))
+- Fixed a bug where containers restored with `podman container restore --import` would incorrectly duplicate the Conmon PID file of the original container
+- Fixed a bug where `podman build` ignored the default OCI runtime configured in `libpod.conf`
+- Fixed a bug where `podman run --rm` (or force-removing any running container with `podman rm --force`) were not retrieving the correct exit code ([#3795](https://github.com/containers/libpod/issues/3795))
+- Fixed a bug where Podman would exit with an error if any configured hooks directory was not present
+- Fixed a bug where `podman inspect` and `podman commit` would not use the correct `CMD` for containers run with `podman play kube`
+- Fixed a bug created pods when using rootless Podman and CGroups V2 ([#3801](https://github.com/containers/libpod/issues/3801))
+- Fixed a bug where the `podman events` command with the `--since` or `--until` options could take a very long time to complete
+
+### Misc
+- Rootless Podman will now inherit OCI runtime configuration from the root configuration ([#3781](https://github.com/containers/libpod/issues/3781))
+- Podman now properly sets a user agent while contacting registries ([#3788](https://github.com/containers/libpod/issues/3788))
+
## 1.5.0
### Features
- Podman containers can now join the user namespaces of other containers with `--userns=container:$ID`, or a user namespace at an arbitary path with `--userns=ns:$PATH`
diff --git a/changelog.txt b/changelog.txt
index beea8dd5c..b0a847aee 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,51 @@
+- Changelog for v1.5.1 (2019-08-15)
+ * Add release notes for v1.5.1
+ * Set Pod hostname as Pod name
+ * tests for exit status on podman run --rm
+ * performance fix for podman events with large journalds
+ * pkg/cgroups: use DBUS session when rootless
+ * Fix play kube command in pod yaml
+ * removMergeDir from inspect result if not mounted
+ * Running Podman with a nonexistent hooks dir is nonfatal
+ * Cirrus: Install varlink on Ubuntu
+ * Cirrus: Install varlink on Fedora
+ * Add missing stage-packages in snapcraft.yaml.
+ * Add RHEL and SUSE to snap doc
+ * start groundwork for adding snap
+ * Add user systemd service and socket
+ * Small optimization - only store exit code when nonzero
+ * Fix container exit code with Journald backend
+ * Revert "Cirrus: Temp. workaround missing imgprune image"
+ * Homebrew installation in install.md
+ * varlink endpoint for containerstats requires root
+ * Adjust get_ci_vm.sh for substitution
+ * Cirrus: Add verification for cgroupv2 image
+ * Cirrus: Add experimental fedora VM image & test
+ * image: add user agent to Docker registry options
+ * Cirrus: Minor, use newer Ubuntu base image
+ * tests: disable some tests currently failing when not using runc
+ * containers: look also for 'file not found' in the error message
+ * cirrus: add tests with crun on Fedora 30
+ * rootless: cherry-pick runtime from the system configuration
+ * cirrus: install crun
+ * cmd: drop check for euid==0
+ * storage: drop unused geteuid check
+ * cmd, stats: fix check for rootless mode
+ * oci: drop check for euid==0
+ * build: use the configured runtime
+ * Adjust read count so that a newline can be added afterwards
+ * Fix incorrect use of realloc()
+ * Bump gitvalidation epoch
+ * Bump to v1.5.1-dev
+ * Fix a couple of errors descovered by coverity
+ * Test that restored container does not depend on the original container
+ * Fix up ConmonPidFile after restore
+ * Cirrus: Enable updates-testing repo for Fedora
+ * enable windows remote client
+ * implement 'make remotesystem'
+ * Squish a few tpyo nits in container.go doc
+ * Cirrus: Add Second partition for storage testing
+
- Changelog for v1.5.0 (2019-08-09)
* vendor github.com/containers/storage@v1.13.2
* Improve dns-search validation, empty domains now return an error
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index d5098ee51..f7c78908f 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -258,6 +258,20 @@ type MountValues struct {
Latest bool
}
+type NetworkListValues struct {
+ PodmanCommand
+ Filter []string
+ Quiet bool
+}
+
+type NetworkRmValues struct {
+ PodmanCommand
+}
+
+type NetworkInspectValues struct {
+ PodmanCommand
+}
+
type PauseValues struct {
PodmanCommand
All bool
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 1e9092bd6..32478bb51 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -388,6 +388,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"publish-all", "P", false,
"Publish all exposed ports to random ports on the host interface",
)
+ createFlags.String(
+ "pull", "missing",
+ `Pull image before creating ("always"|"missing"|"never") (default "missing")`,
+ )
createFlags.BoolP(
"quiet", "q", false,
"Suppress output information when pulling images",
diff --git a/cmd/podman/network.go b/cmd/podman/network.go
new file mode 100644
index 000000000..83a5e71ab
--- /dev/null
+++ b/cmd/podman/network.go
@@ -0,0 +1,31 @@
+//+build !remoteclient
+
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/spf13/cobra"
+)
+
+var networkcheckDescription = "Manage networks"
+var networkcheckCommand = cliconfig.PodmanCommand{
+ Command: &cobra.Command{
+ Use: "network",
+ Short: "Manage Networks",
+ Long: networkcheckDescription,
+ RunE: commandRunE(),
+ },
+}
+
+// Commands that are universally implemented
+var networkcheckCommands = []*cobra.Command{
+ _networkinspectCommand,
+ _networklistCommand,
+ _networkrmCommand,
+}
+
+func init() {
+ networkcheckCommand.AddCommand(networkcheckCommands...)
+ networkcheckCommand.SetUsageTemplate(UsageTemplate())
+ rootCmd.AddCommand(networkcheckCommand.Command)
+}
diff --git a/cmd/podman/network_inspect.go b/cmd/podman/network_inspect.go
new file mode 100644
index 000000000..38aaf6ba4
--- /dev/null
+++ b/cmd/podman/network_inspect.go
@@ -0,0 +1,48 @@
+// +build !remoteclient
+
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ networkinspectCommand cliconfig.NetworkInspectValues
+ networkinspectDescription = `Inspect network`
+ _networkinspectCommand = &cobra.Command{
+ Use: "inspect NETWORK [NETWORK...] [flags] ",
+ Short: "network inspect",
+ Long: networkinspectDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ networkinspectCommand.InputArgs = args
+ networkinspectCommand.GlobalFlags = MainGlobalOpts
+ networkinspectCommand.Remote = remoteclient
+ return networkinspectCmd(&networkinspectCommand)
+ },
+ Example: `podman network inspect podman`,
+ }
+)
+
+func init() {
+ networkinspectCommand.Command = _networkinspectCommand
+ networkinspectCommand.SetHelpTemplate(HelpTemplate())
+ networkinspectCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func networkinspectCmd(c *cliconfig.NetworkInspectValues) error {
+ if rootless.IsRootless() && !remoteclient {
+ return errors.New("network inspect is not supported for rootless mode")
+ }
+ if len(c.InputArgs) < 1 {
+ return errors.Errorf("at least one network name is required")
+ }
+ runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return err
+ }
+ return runtime.NetworkInspect(c)
+}
diff --git a/cmd/podman/network_list.go b/cmd/podman/network_list.go
new file mode 100644
index 000000000..16edf743b
--- /dev/null
+++ b/cmd/podman/network_list.go
@@ -0,0 +1,53 @@
+// +build !remoteclient
+
+package main
+
+import (
+ "errors"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/spf13/cobra"
+)
+
+var (
+ networklistCommand cliconfig.NetworkListValues
+ networklistDescription = `List networks`
+ _networklistCommand = &cobra.Command{
+ Use: "ls",
+ Args: noSubArgs,
+ Short: "network list",
+ Long: networklistDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ networklistCommand.InputArgs = args
+ networklistCommand.GlobalFlags = MainGlobalOpts
+ networklistCommand.Remote = remoteclient
+ return networklistCmd(&networklistCommand)
+ },
+ Example: `podman network list`,
+ }
+)
+
+func init() {
+ networklistCommand.Command = _networklistCommand
+ networklistCommand.SetHelpTemplate(HelpTemplate())
+ networklistCommand.SetUsageTemplate(UsageTemplate())
+ flags := networklistCommand.Flags()
+ // TODO enable filters based on something
+ //flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
+ flags.BoolVarP(&networklistCommand.Quiet, "quiet", "q", false, "display only names")
+}
+
+func networklistCmd(c *cliconfig.NetworkListValues) error {
+ if rootless.IsRootless() && !remoteclient {
+ return errors.New("network list is not supported for rootless mode")
+ }
+ if len(c.InputArgs) > 0 {
+ return errors.New("network list takes no arguments")
+ }
+ runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return err
+ }
+ return runtime.NetworkList(c)
+}
diff --git a/cmd/podman/network_rm.go b/cmd/podman/network_rm.go
new file mode 100644
index 000000000..50bd48cea
--- /dev/null
+++ b/cmd/podman/network_rm.go
@@ -0,0 +1,48 @@
+// +build !remoteclient
+
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ networkrmCommand cliconfig.NetworkRmValues
+ networkrmDescription = `Remove networks`
+ _networkrmCommand = &cobra.Command{
+ Use: "rm [flags] NETWORK [NETWORK...]",
+ Short: "network rm",
+ Long: networkrmDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ networkrmCommand.InputArgs = args
+ networkrmCommand.GlobalFlags = MainGlobalOpts
+ networkrmCommand.Remote = remoteclient
+ return networkrmCmd(&networkrmCommand)
+ },
+ Example: `podman network rm podman`,
+ }
+)
+
+func init() {
+ networkrmCommand.Command = _networkrmCommand
+ networkrmCommand.SetHelpTemplate(HelpTemplate())
+ networkrmCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func networkrmCmd(c *cliconfig.NetworkRmValues) error {
+ if rootless.IsRootless() && !remoteclient {
+ return errors.New("network rm is not supported for rootless mode")
+ }
+ if len(c.InputArgs) < 1 {
+ return errors.Errorf("at least one network name is required")
+ }
+ runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return err
+ }
+ return runtime.NetworkRemove(c)
+}
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 0eee51e79..53f133929 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -150,7 +150,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
// See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background
// information.
if !c.Bool("all-tags") {
- newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil)
+ newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
return errors.Wrapf(err, "error pulling image %q", imgArg)
}
@@ -188,7 +188,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
var foundIDs []string
foundImage := true
for _, name := range names {
- newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil)
+ newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
logrus.Errorf("error pulling image %q", name)
foundImage = false
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index 1d35ac17b..5122d37d1 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -732,7 +732,7 @@ func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtim
registryCreds = creds
}
dockerRegistryOptions.DockerRegistryCreds = registryCreds
- newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, false, &label)
+ newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, &label, util.PullImageMissing)
} else {
newImage, err = runtime.ImageRuntime().NewFromLocal(runlabelImage)
}
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index e29e6b28e..094330e24 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -83,7 +83,13 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
} else {
return nil, nil, errors.Errorf("error, no input arguments were provided")
}
- newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, GetAuthFile(c.String("authfile")), writer, nil, image.SigningOptions{}, false, nil)
+
+ pullType, err := util.ValidatePullType(c.String("pull"))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, GetAuthFile(c.String("authfile")), writer, nil, image.SigningOptions{}, nil, pullType)
if err != nil {
return nil, nil, err
}
diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go
index 3479876b4..c6c32f8a9 100644
--- a/cmd/podman/shared/intermediate.go
+++ b/cmd/podman/shared/intermediate.go
@@ -436,6 +436,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes
m["privileged"] = newCRBool(c, "privileged")
m["publish"] = newCRStringSlice(c, "publish")
m["publish-all"] = newCRBool(c, "publish-all")
+ m["pull"] = newCRString(c, "pull")
m["quiet"] = newCRBool(c, "quiet")
m["read-only"] = newCRBool(c, "read-only")
m["read-only-tmpfs"] = newCRBool(c, "read-only-tmpfs")
diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go
index 4742d4909..9dbf83950 100644
--- a/cmd/podman/shared/intermediate_varlink.go
+++ b/cmd/podman/shared/intermediate_varlink.go
@@ -137,6 +137,7 @@ func (g GenericCLIResults) MakeVarlink() iopodman.Create {
Privileged: BoolToPtr(g.Find("privileged")),
Publish: StringSliceToPtr(g.Find("publish")),
PublishAll: BoolToPtr(g.Find("publish-all")),
+ Pull: StringToPtr(g.Find("pull")),
Quiet: BoolToPtr(g.Find("quiet")),
Readonly: BoolToPtr(g.Find("read-only")),
Readonlytmpfs: BoolToPtr(g.Find("read-only-tmpfs")),
@@ -393,6 +394,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
m["privileged"] = boolFromVarlink(opts.Privileged, "privileged", false)
m["publish"] = stringSliceFromVarlink(opts.Publish, "publish", nil)
m["publish-all"] = boolFromVarlink(opts.PublishAll, "publish-all", false)
+ m["pull"] = stringFromVarlink(opts.Pull, "missing", nil)
m["quiet"] = boolFromVarlink(opts.Quiet, "quiet", false)
m["read-only"] = boolFromVarlink(opts.Readonly, "read-only", false)
m["read-only-tmpfs"] = boolFromVarlink(opts.Readonlytmpfs, "read-only-tmpfs", true)
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index 1333cf441..de289047a 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -15,6 +15,7 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/trust"
+ "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -113,7 +114,7 @@ func signCmd(c *cliconfig.SignValues) error {
if err != nil {
return err
}
- newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, false, nil)
+ newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing)
if err != nil {
return errors.Wrapf(err, "error pulling image %s", signimage)
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 4a4c97e99..2e7dee94d 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -347,6 +347,7 @@ type Create (
privileged: ?bool,
publish: ?[]string,
publishAll: ?bool,
+ pull: ?string,
quiet: ?bool,
readonly: ?bool,
readonlytmpfs: ?bool,
diff --git a/commands.md b/commands.md
index 1b48d7862..4d3bea439 100644
--- a/commands.md
+++ b/commands.md
@@ -44,6 +44,10 @@
| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
+| [podman-network(1)](/docs/podman-network.1.md) | Manage Podman CNI networks |
+| [podman-network-inspect(1)](/docs/podman-network-inspect.1.md) | Inspect one or more Podman networks |
+| [podman-network-ls(1)](/docs/podman-network-ls.1.md) | Display a summary of Podman networks |
+| [podman-network-rm(1)](/docs/podman-network-rm.1.md) | Remove one or more Podman networks |
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://podman.io/asciinema/podman/pause_unpause/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_pause_unpause.sh) |
| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
diff --git a/completions/bash/podman b/completions/bash/podman
index d2eb5b570..962c15a95 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -946,6 +946,78 @@ _podman_healthcheck() {
esac
}
+_podman_network() {
+ local boolean_options="
+ --help
+ -h
+ "
+ subcommands="
+ inspect
+ ls
+ rm
+ "
+ __podman_subcommands "$subcommands $aliases" && return
+
+ case "$cur" in
+ -*)
+ COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
+ ;;
+ *)
+ COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) )
+ ;;
+ esac
+}
+
+_podman_network_inspect() {
+ local options_with_args="
+ "
+ local boolean_options="
+ --help
+ -h
+ "
+ _complete_ "$options_with_args" "$boolean_options"
+
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
+_podman_network_ls() {
+ local options_with_args="
+ "
+ local boolean_options="
+ --help
+ -h
+ --quiet
+ -q
+ "
+ _complete_ "$options_with_args" "$boolean_options"
+
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
+_podman_network_ls() {
+ local options_with_args="
+ "
+ local boolean_options="
+ --help
+ -h
+ "
+ _complete_ "$options_with_args" "$boolean_options"
+
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
_podman_generate() {
local boolean_options="
--help
@@ -1773,6 +1845,7 @@ _podman_container_run() {
--pids-limit
--pod
--publish -p
+ --pull
--runtime
--rootfs
--security-opt
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index 8a43176e4..e5de518fa 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -37,11 +37,16 @@ case "$SPECIALMODE" in
-o CheckHostIP=no $GOSRC/$SCRIPT_BASE/rootless_test.sh ${TESTSUITE}
;;
cgroupv2)
+ # FIXME: use the package once all the fixes are in a release
+ # yum install -y crun
+ setenforce 0
+ yum builddep -y crun
+ (git clone --depth=1 https://github.com/containers/crun && cd crun && ./autogen.sh && ./configure --prefix=/usr && make -j4 && make install)
+ export OCI_RUNTIME=/usr/bin/crun
make
make install PREFIX=/usr ETCDIR=/etc
make test-binaries
- echo "WARNING: Integration tests not yet ready for cgroups V2"
- #TODO: make local${TESTSUITE}
+ make local${TESTSUITE}
;;
none)
make
diff --git a/contrib/cirrus/networking.sh b/contrib/cirrus/networking.sh
new file mode 100755
index 000000000..aeaf74035
--- /dev/null
+++ b/contrib/cirrus/networking.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# This script attempts basic confirmation of functional networking
+# by connecting to a set of essential external servers and failing
+# if any cannot be reached.
+
+source $(dirname $0)/lib.sh
+
+while read host port
+do
+ if [[ "$port" -eq "443" ]]
+ then
+ item_test "SSL/TLS to $host:$port" "$(echo -n '' | openssl s_client -quiet -no_ign_eof -connect $host:$port &> /dev/null; echo $?)" -eq "0"
+ else
+ item_test "Connect to $host:$port" "$(nc -zv -w 13 $host $port &> /dev/null; echo $?)" -eq 0
+ fi
+done < ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/required_host_ports.txt
diff --git a/contrib/cirrus/required_host_ports.txt b/contrib/cirrus/required_host_ports.txt
index 9248e497a..85a6c26be 100644
--- a/contrib/cirrus/required_host_ports.txt
+++ b/contrib/cirrus/required_host_ports.txt
@@ -2,3 +2,14 @@ github.com 22
docker.io 443
quay.io 443
registry.fedoraproject.org 443
+mirrors.fedoraproject.org 443
+dl.fedoraproject.org 443
+ewr.edge.kernel.org 443
+mirror.chpc.utah.edu 443
+mirror.clarkson.edu 443
+mirror.umd.edu 443
+mirror.vcu.edu 443
+mirrors.cat.pdx.edu 443
+pubmirror1.math.uh.edu 443
+pubmirror2.math.uh.edu 443
+sjc.edge.kernel.org 443
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 03acaf1da..7b6765f8a 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -44,11 +44,6 @@ case "${OS_REL_VER}" in
;;
fedora-30) ;& # continue to next item
fedora-29)
- # There is no crun package on Fedora29
- if test "${OS_REL_VER}" != "fedora-29"; then
- yum install -y crun
- fi
-
if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then
bash "$SCRIPT_BASE/add_second_partition.sh"; fi
;;
diff --git a/contrib/perftest/main.go b/contrib/perftest/main.go
index 237f4f6e6..f6c90914a 100644
--- a/contrib/perftest/main.go
+++ b/contrib/perftest/main.go
@@ -103,7 +103,7 @@ func main() {
}
fmt.Printf("image %s not found locally, fetching from remote registry..\n", *testImageName)
- testImage, err = client.ImageRuntime().New(ctx, *testImageName, "", "", writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
+ testImage, err = client.ImageRuntime().New(ctx, *testImageName, "", "", writer, &dockerRegistryOptions, image2.SigningOptions{}, nil, util.PullImageMissing)
if err != nil {
logrus.Fatal(err)
}
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 35f3b2014..934f785db 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -39,7 +39,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.5.1
+Version: 1.5.2
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 50fca3541..1377f2a03 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -582,6 +582,15 @@ port to a random port on the host within an *ephemeral port range* defined by
`/proc/sys/net/ipv4/ip_local_port_range`. To find the mapping between the host
ports and the exposed ports, use `podman port`.
+**--pull**=*missing*
+
+Pull image before creating ("always"|"missing"|"never") (default "missing").
+ 'missing': default value, attempt to pull the latest image from the registries listed in registries.conf if a local image does not exist.Raise an error if the image is not in any listed registry and is not present locally.
+ 'always': Pull the image from the first registry it is found in as listed in registries.conf. Raise an error if not found in the registries, even if the image is present locally.
+ 'never': do not pull the image from the registry, use only the local version. Raise an error if the image is not present locally.
+
+Defaults to *missing*.
+
**--quiet**, **-q**
Suppress output information when pulling images
@@ -715,7 +724,7 @@ $ podman run -d --tmpfs /tmp:rw,size=787448k,mode=1777 my_image
This command mounts a `tmpfs` at `/tmp` within the container. The supported mount
options are the same as the Linux default `mount` flags. If you do not specify
any options, the systems uses the following options:
-`rw,noexec,nosuid,nodev,size=65536k`.
+`rw,noexec,nosuid,nodev`.
**--tty**, **-t**=*true|false*
diff --git a/docs/podman-network-inspect.1.md b/docs/podman-network-inspect.1.md
new file mode 100644
index 000000000..576e61c79
--- /dev/null
+++ b/docs/podman-network-inspect.1.md
@@ -0,0 +1,50 @@
+% podman-network-inspect(1)
+
+## NAME
+podman\-network-inspect- Inspect one or more Podman networks
+
+## SYNOPSIS
+**podman network inspect** [*network* ...]
+
+## DESCRIPTION
+Display the raw (JSON format) network configuration. This command is not available for rootless users.
+
+## EXAMPLE
+
+Inspect the default podman network
+
+```
+# podman network inspect podman
+[{
+ "cniVersion": "0.3.0",
+ "name": "podman",
+ "plugins": [
+ {
+ "type": "bridge",
+ "bridge": "cni0",
+ "isGateway": true,
+ "ipMasq": true,
+ "ipam": {
+ "type": "host-local",
+ "subnet": "10.88.1.0/24",
+ "routes": [
+ { "dst": "0.0.0.0/0" }
+ ]
+ }
+ },
+ {
+ "type": "portmap",
+ "capabilities": {
+ "portMappings": true
+ }
+ }
+ ]
+}
+]
+```
+
+## SEE ALSO
+podman(1), podman-network(1), podman-network-ls(1)
+
+## HISTORY
+August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/podman-network-ls.1.md b/docs/podman-network-ls.1.md
new file mode 100644
index 000000000..725e07dbb
--- /dev/null
+++ b/docs/podman-network-ls.1.md
@@ -0,0 +1,43 @@
+% podman-network-ls(1)
+
+## NAME
+podman\-network-ls- Display a summary of CNI networks
+
+## SYNOPSIS
+**podman network ls** [*options*]
+
+## DESCRIPTION
+Displays a list of existing podman networks. This command is not available for rootless users.
+
+## OPTIONS
+**--quiet**, **-q**
+
+The `quiet` options will restrict the output to only the network names
+
+## EXAMPLE
+
+Display networks
+
+```
+# podman network ls
+NAME VERSION PLUGINS
+podman 0.3.0 bridge,portmap
+podman2 0.3.0 bridge,portmap
+outside 0.3.0 bridge
+podman9 0.3.0 bridge,portmap
+```
+
+Display only network names
+```
+# podman network ls -q
+podman
+podman2
+outside
+podman9
+```
+
+## SEE ALSO
+podman(1), podman-network(1), podman-network-inspect(1)
+
+## HISTORY
+August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/podman-network-rm.1.md b/docs/podman-network-rm.1.md
new file mode 100644
index 000000000..f72d6a694
--- /dev/null
+++ b/docs/podman-network-rm.1.md
@@ -0,0 +1,25 @@
+% podman-network-rm(1)
+
+## NAME
+podman\-network-rm- Delete a Podman CNI network
+
+## SYNOPSIS
+**podman network rm** [*network...*]
+
+## DESCRIPTION
+Delete one or more Podman networks.
+
+## EXAMPLE
+
+Delete the `podman9` network
+
+```
+# podman network rm podman
+Deleted: podman9
+```
+
+## SEE ALSO
+podman(1), podman-network(1), podman-network-inspect(1)
+
+## HISTORY
+August 2019, Originally compiled by Brent Baude <bbaude@redhat.com>
diff --git a/docs/podman-network.1.md b/docs/podman-network.1.md
new file mode 100644
index 000000000..c01adc23e
--- /dev/null
+++ b/docs/podman-network.1.md
@@ -0,0 +1,21 @@
+% podman-network(1)
+
+## NAME
+podman\-network- Manage podman CNI networks
+
+## SYNOPSIS
+**podman network** *subcommand*
+
+## DESCRIPTION
+The network command manages CNI networks for Podman. It is not supported for rootless users.
+
+## COMMANDS
+
+| Command | Man Page | Description |
+| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
+| inspect | [podman-network-inspect(1)](podman-network-inspect.1.md)| Displays the raw CNI network configuration for one or more networks|
+| ls | [podman-network-ls(1)](podman-network-ls.1.md)| Display a summary of CNI networks |
+| rm | [podman-network-rm(1)](podman-network-rm.1.md)| Remove one or more CNI networks |
+
+## SEE ALSO
+podman(1)
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index e7c898b25..2445df566 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -601,6 +601,15 @@ When using -P, podman will bind any exposed port to a random port on the host
within an *ephemeral port range* defined by `/proc/sys/net/ipv4/ip_local_port_range`.
To find the mapping between the host ports and the exposed ports, use `podman port`.
+**--pull**=*missing*
+
+Pull image before running ("always"|"missing"|"never") (default "missing").
+ 'missing': default value, attempt to pull the latest image from the registries listed in registries.conf if a local image does not exist.Raise an error if the image is not in any listed registry and is not present locally.
+ 'always': Pull the image from the first registry it is found in as listed in registries.conf. Raise an error if not found in the registries, even if the image is present locally.
+ 'never': do not pull the image from the registry, use only the local version. Raise an error if the image is not present locally.
+
+Defaults to *missing*.
+
**--quiet**, **-q**
Suppress output information when pulling images
@@ -752,7 +761,7 @@ $ podman run -d --tmpfs /tmp:rw,size=787448k,mode=1777 my_image
This command mounts a `tmpfs` at `/tmp` within the container. The supported mount
options are the same as the Linux default `mount` flags. If you do not specify
any options, the systems uses the following options:
-`rw,noexec,nosuid,nodev,size=65536k`.
+`rw,noexec,nosuid,nodev`.
**--tty**, **-t**=*true|false*
diff --git a/docs/podman.1.md b/docs/podman.1.md
index 12b7866ca..33ea81ef6 100644
--- a/docs/podman.1.md
+++ b/docs/podman.1.md
@@ -161,6 +161,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. |
| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
+| [podman-network(1)](podman-network.1.md) | Manage Podman CNI networks. |
| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 068491f28..cb7c390c6 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -135,7 +135,7 @@ func (ir *Runtime) NewFromLocal(name string) (*Image, error) {
// New creates a new image object where the image could be local
// or remote
-func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *DockerRegistryOptions, signingoptions SigningOptions, forcePull bool, label *string) (*Image, error) {
+func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *DockerRegistryOptions, signingoptions SigningOptions, label *string, pullType util.PullType) (*Image, error) {
span, _ := opentracing.StartSpanFromContext(ctx, "newImage")
span.SetTag("type", "runtime")
defer span.Finish()
@@ -145,11 +145,13 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile
InputName: name,
imageruntime: ir,
}
- if !forcePull {
+ if pullType != util.PullImageAlways {
localImage, err := newImage.getLocalImage()
if err == nil {
newImage.image = localImage
return &newImage, nil
+ } else if pullType == util.PullImageNever {
+ return nil, err
}
}
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index e93ebf797..5a6d095f6 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -3,12 +3,13 @@ package image
import (
"context"
"fmt"
- "github.com/containers/libpod/libpod/events"
"io"
"io/ioutil"
"os"
"testing"
+ "github.com/containers/libpod/libpod/events"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
"github.com/opencontainers/go-digest"
"github.com/stretchr/testify/assert"
@@ -89,9 +90,9 @@ func TestImage_NewFromLocal(t *testing.T) {
ir, err := NewImageRuntimeFromOptions(so)
assert.NoError(t, err)
ir.Eventer = events.NewNullEventer()
- bb, err := ir.New(context.Background(), "docker.io/library/busybox:latest", "", "", writer, nil, SigningOptions{}, false, nil)
+ bb, err := ir.New(context.Background(), "docker.io/library/busybox:latest", "", "", writer, nil, SigningOptions{}, nil, util.PullImageMissing)
assert.NoError(t, err)
- bbglibc, err := ir.New(context.Background(), "docker.io/library/busybox:glibc", "", "", writer, nil, SigningOptions{}, false, nil)
+ bbglibc, err := ir.New(context.Background(), "docker.io/library/busybox:glibc", "", "", writer, nil, SigningOptions{}, nil, util.PullImageMissing)
assert.NoError(t, err)
tm, err := makeLocalMatrix(bb, bbglibc)
@@ -139,7 +140,7 @@ func TestImage_New(t *testing.T) {
// Iterate over the names and delete the image
// after the pull
for _, img := range names {
- newImage, err := ir.New(context.Background(), img, "", "", writer, nil, SigningOptions{}, false, nil)
+ newImage, err := ir.New(context.Background(), img, "", "", writer, nil, SigningOptions{}, nil, util.PullImageMissing)
assert.NoError(t, err)
assert.NotEqual(t, newImage.ID(), "")
err = newImage.Remove(context.Background(), false)
@@ -168,7 +169,7 @@ func TestImage_MatchRepoTag(t *testing.T) {
ir, err := NewImageRuntimeFromOptions(so)
assert.NoError(t, err)
ir.Eventer = events.NewNullEventer()
- newImage, err := ir.New(context.Background(), "busybox", "", "", os.Stdout, nil, SigningOptions{}, false, nil)
+ newImage, err := ir.New(context.Background(), "busybox", "", "", os.Stdout, nil, SigningOptions{}, nil, util.PullImageMissing)
assert.NoError(t, err)
err = newImage.TagImage("foo:latest")
assert.NoError(t, err)
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index da35b7f93..5387eb587 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
"github.com/opencontainers/image-spec/specs-go/v1"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
@@ -30,6 +31,9 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
return nil, err
}
+ // Set Pod hostname as Pod name
+ g.Config.Hostname = p.config.Name
+
isRootless := rootless.IsRootless()
entryCmd := []string{r.config.InfraCommand}
@@ -108,7 +112,7 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container,
return nil, define.ErrRuntimeStopped
}
- newImage, err := r.ImageRuntime().New(ctx, r.config.InfraImage, "", "", nil, nil, image.SigningOptions{}, false, nil)
+ newImage, err := r.ImageRuntime().New(ctx, r.config.InfraImage, "", "", nil, nil, image.SigningOptions{}, nil, util.PullImageMissing)
if err != nil {
return nil, err
}
diff --git a/pkg/adapter/checkpoint_restore.go b/pkg/adapter/checkpoint_restore.go
index 1cac86d12..15f9e8105 100644
--- a/pkg/adapter/checkpoint_restore.go
+++ b/pkg/adapter/checkpoint_restore.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/errorhandling"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage/pkg/archive"
jsoniter "github.com/json-iterator/go"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -112,7 +113,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri
return nil, err
}
- _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, false, nil)
+ _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing)
if err != nil {
return nil, err
}
diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go
new file mode 100644
index 000000000..cf3a1dfdd
--- /dev/null
+++ b/pkg/adapter/network.go
@@ -0,0 +1,147 @@
+// +build !remoteclient
+
+package adapter
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/containernetworking/cni/libcni"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/network"
+ "github.com/pkg/errors"
+)
+
+func getCNIConfDir(r *LocalRuntime) (string, error) {
+ config, err := r.GetConfig()
+ if err != nil {
+ return "", err
+ }
+ configPath := config.CNIConfigDir
+
+ if len(config.CNIConfigDir) < 1 {
+ configPath = network.CNIConfigDir
+ }
+ return configPath, nil
+}
+
+// NetworkList displays summary information about CNI networks
+func (r *LocalRuntime) NetworkList(cli *cliconfig.NetworkListValues) error {
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ networks, err := network.LoadCNIConfsFromDir(cniConfigPath)
+ if err != nil {
+ return err
+ }
+ // quiet means we only print the network names
+ if cli.Quiet {
+ for _, cniNetwork := range networks {
+ fmt.Println(cniNetwork.Name)
+ }
+ return nil
+ }
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
+ if _, err := fmt.Fprintln(w, "NAME\tVERSION\tPLUGINS"); err != nil {
+ return err
+ }
+ for _, cniNetwork := range networks {
+ if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", cniNetwork.Name, cniNetwork.CNIVersion, getCNIPlugins(cniNetwork)); err != nil {
+ return err
+ }
+ }
+ return w.Flush()
+}
+
+// NetworkInspect displays the raw CNI configuration for one
+// or more CNI networks
+func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error {
+ var (
+ rawCNINetworks []map[string]interface{}
+ )
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ for _, name := range cli.InputArgs {
+ b, err := readRawCNIConfByName(name, cniConfigPath)
+ if err != nil {
+ return err
+ }
+ rawList := make(map[string]interface{})
+ if err := json.Unmarshal(b, &rawList); err != nil {
+ return fmt.Errorf("error parsing configuration list: %s", err)
+ }
+ rawCNINetworks = append(rawCNINetworks, rawList)
+ }
+ out, err := json.MarshalIndent(rawCNINetworks, "", "\t")
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s\n", out)
+ return nil
+}
+
+// NetworkRemove deletes one or more CNI networks
+func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error {
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ for _, name := range cli.InputArgs {
+ cniPath, err := getCNIConfigPathByName(name, cniConfigPath)
+ if err != nil {
+ return err
+ }
+ if err := os.Remove(cniPath); err != nil {
+ return err
+ }
+ fmt.Printf("Deleted: %s\n", name)
+ }
+ return nil
+}
+
+// getCNIConfigPathByName finds a CNI network by name and
+// returns its configuration file path
+func getCNIConfigPathByName(name, cniConfigPath string) (string, error) {
+ files, err := libcni.ConfFiles(cniConfigPath, []string{".conflist"})
+ if err != nil {
+ return "", err
+ }
+ for _, confFile := range files {
+ conf, err := libcni.ConfListFromFile(confFile)
+ if err != nil {
+ return "", err
+ }
+ if conf.Name == name {
+ return confFile, nil
+ }
+ }
+ return "", errors.Errorf("unable to find network configuration for %s", name)
+}
+
+// readRawCNIConfByName reads the raw CNI configuration for a CNI
+// network by name
+func readRawCNIConfByName(name, cniConfigPath string) ([]byte, error) {
+ confFile, err := getCNIConfigPathByName(name, cniConfigPath)
+ if err != nil {
+ return nil, err
+ }
+ b, err := ioutil.ReadFile(confFile)
+ return b, err
+}
+
+// getCNIPlugins returns a list of plugins that a given network
+// has in the form of a string
+func getCNIPlugins(list *libcni.NetworkConfigList) string {
+ var plugins []string
+ for _, plug := range list.Plugins {
+ plugins = append(plugins, plug.Network.Type)
+ }
+ return strings.Join(plugins, ",")
+}
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index 2743dfdc6..1dd72babf 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/libpod/pkg/adapter/shortcuts"
ns "github.com/containers/libpod/pkg/namespaces"
createconfig "github.com/containers/libpod/pkg/spec"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/ghodss/yaml"
@@ -578,7 +579,7 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa
}
for _, container := range podYAML.Spec.Containers {
- newImage, err := r.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, false, nil)
+ newImage, err := r.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageMissing)
if err != nil {
return nil, err
}
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index 03419c0bd..ba988aaf7 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -24,6 +24,7 @@ import (
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"k8s.io/api/core/v1"
@@ -132,8 +133,8 @@ func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef type
}
// New calls into local storage to look for an image in local storage or to pull it
-func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) {
- img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, forcePull, label)
+func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, label *string, pullType util.PullType) (*ContainerImage, error) {
+ img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, label, pullType)
if err != nil {
return nil, err
}
@@ -288,7 +289,11 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti
options.CommonBuildOpts = commonOpts
options.SystemContext = systemContext
- options.Runtime = r.GetOCIRuntimePath()
+ if c.GlobalFlags.Runtime != "" {
+ options.Runtime = c.GlobalFlags.Runtime
+ } else {
+ options.Runtime = r.GetOCIRuntimePath()
+ }
if c.Quiet {
options.ReportWriter = ioutil.Discard
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 0cafbb2aa..420c9d0bb 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -26,6 +26,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/utils"
"github.com/containers/storage/pkg/archive"
"github.com/opencontainers/go-digest"
@@ -272,7 +273,7 @@ func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef type
}
// New calls into local storage to look for an image in local storage or to pull it
-func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, forcePull bool, label *string) (*ContainerImage, error) {
+func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, label *string, pullType util.PullType) (*ContainerImage, error) {
var iid string
if label != nil {
return nil, errors.New("the remote client function does not support checking a remote image for a label")
diff --git a/pkg/network/config.go b/pkg/network/config.go
new file mode 100644
index 000000000..d282f66b6
--- /dev/null
+++ b/pkg/network/config.go
@@ -0,0 +1,4 @@
+package network
+
+// CNIConfigDir is the path where CNI config files exist
+const CNIConfigDir = "/etc/cni/net.d"
diff --git a/pkg/network/network.go b/pkg/network/network.go
new file mode 100644
index 000000000..9d04340a3
--- /dev/null
+++ b/pkg/network/network.go
@@ -0,0 +1,26 @@
+package network
+
+import (
+ "sort"
+
+ "github.com/containernetworking/cni/libcni"
+)
+
+// LoadCNIConfsFromDir loads all the CNI configurations from a dir
+func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
+ var configs []*libcni.NetworkConfigList
+ files, err := libcni.ConfFiles(dir, []string{".conflist"})
+ if err != nil {
+ return nil, err
+ }
+ sort.Strings(files)
+
+ for _, confFile := range files {
+ conf, err := libcni.ConfListFromFile(confFile)
+ if err != nil {
+ return nil, err
+ }
+ configs = append(configs, conf)
+ }
+ return configs, nil
+}
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index a8dc7f4a8..b634f4cac 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -168,14 +168,14 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
"/run": false,
}
if config.ReadOnlyRootfs && config.ReadOnlyTmpfs {
- options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup", "size=65536k"}
+ options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup"}
for dest := range readonlyTmpfs {
if _, ok := baseMounts[dest]; ok {
continue
}
localOpts := options
if dest == "/run" {
- localOpts = append(localOpts, "noexec")
+ localOpts = append(localOpts, "noexec", "size=65536k")
}
baseMounts[dest] = spec.Mount{
Destination: dest,
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index 40c99384d..9b2c734c0 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -92,9 +92,6 @@ func ProcessTmpfsOptions(options []string) ([]string, error) {
if !foundWrite {
baseOpts = append(baseOpts, "rw")
}
- if !foundSize {
- baseOpts = append(baseOpts, "size=65536k")
- }
if !foundProp {
baseOpts = append(baseOpts, "rprivate")
}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 520e41438..3f73639e7 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -356,3 +356,32 @@ func OpenExclusiveFile(path string) (*os.File, error) {
}
return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
}
+
+// PullType whether to pull new image
+type PullType int
+
+const (
+ // PullImageAlways always try to pull new image when create or run
+ PullImageAlways PullType = iota
+ // PullImageMissing pulls image if it is not locally
+ PullImageMissing
+ // PullImageNever will never pull new image
+ PullImageNever
+)
+
+// ValidatePullType check if the pullType from CLI is valid and returns the valid enum type
+// if the value from CLI is invalid returns the error
+func ValidatePullType(pullType string) (PullType, error) {
+ switch pullType {
+ case "always":
+ return PullImageAlways, nil
+ case "missing":
+ return PullImageMissing, nil
+ case "never":
+ return PullImageNever, nil
+ case "":
+ return PullImageMissing, nil
+ default:
+ return PullImageMissing, errors.Errorf("invalid pull type %q", pullType)
+ }
+}
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index b5a711dfd..fe7f11b4d 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -658,7 +658,7 @@ func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string) error {
imageID = newImage[0].ID()
}
} else {
- newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, "", "", output, &dockerRegistryOptions, so, false, nil)
+ newImage, err := i.Runtime.ImageRuntime().New(getContext(), name, "", "", output, &dockerRegistryOptions, so, nil, util.PullImageMissing)
if err != nil {
foundError = true
c <- errors.Wrapf(err, "unable to pull %s", name)
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index b6dd1ecd1..4e9881d59 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -538,7 +538,7 @@ func (p *PodmanTestIntegration) RunHealthCheck(cid string) error {
return nil
}
// Restart container if it's not running
- ps := p.Podman([]string{"ps", "--no-trunc", "--q", "--filter", fmt.Sprintf("id=%s", cid)})
+ ps := p.Podman([]string{"ps", "--no-trunc", "--quiet", "--filter", fmt.Sprintf("id=%s", cid)})
ps.WaitWithDefaultTimeout()
if ps.ExitCode() == 0 {
if !strings.Contains(ps.OutputToString(), cid) {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 25d0c3390..2918cce78 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -231,4 +231,14 @@ var _ = Describe("Podman create", func() {
Expect(ctrJSON[0].Config.Cmd[0]).To(Equal("redis-server"))
Expect(ctrJSON[0].Config.Entrypoint).To(Equal("docker-entrypoint.sh"))
})
+
+ It("podman create --pull", func() {
+ session := podmanTest.PodmanNoCache([]string{"create", "--pull", "never", "--name=foo", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+
+ session = podmanTest.PodmanNoCache([]string{"create", "--pull", "always", "--name=foo", "nginx"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To((Equal(0)))
+ })
})
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
new file mode 100644
index 000000000..9aed5351a
--- /dev/null
+++ b/test/e2e/network_test.go
@@ -0,0 +1,158 @@
+// +build !remoteclient
+
+package integration
+
+import (
+ "fmt"
+ . "github.com/containers/libpod/test/utils"
+ "github.com/containers/storage/pkg/stringid"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+func writeConf(conf []byte, confPath string) {
+ if err := ioutil.WriteFile(confPath, conf, 777); err != nil {
+ fmt.Println(err)
+ }
+}
+func removeConf(confPath string) {
+ if err := os.Remove(confPath); err != nil {
+ fmt.Println(err)
+ }
+}
+
+var _ = Describe("Podman network", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ var (
+ secondConf = `{
+ "cniVersion": "0.3.0",
+ "name": "podman-integrationtest",
+ "plugins": [
+ {
+ "type": "bridge",
+ "bridge": "cni1",
+ "isGateway": true,
+ "ipMasq": true,
+ "ipam": {
+ "type": "host-local",
+ "subnet": "10.99.0.0/16",
+ "routes": [
+ { "dst": "0.0.0.0/0" }
+ ]
+ }
+ },
+ {
+ "type": "portmap",
+ "capabilities": {
+ "portMappings": true
+ }
+ }
+ ]
+}`
+ cniPath = "/etc/cni/net.d"
+ )
+
+ It("podman network list", func() {
+ SkipIfRootless()
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
+ })
+
+ It("podman network list -q", func() {
+ SkipIfRootless()
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
+ })
+
+ It("podman network rm no args", func() {
+ SkipIfRootless()
+ session := podmanTest.Podman([]string{"network", "rm"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).ToNot(BeZero())
+ })
+
+ It("podman network rm", func() {
+ SkipIfRootless()
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
+
+ rm := podmanTest.Podman([]string{"network", "rm", "podman-integrationtest"})
+ rm.WaitWithDefaultTimeout()
+ Expect(rm.ExitCode()).To(BeZero())
+
+ results := podmanTest.Podman([]string{"network", "ls", "--quiet"})
+ results.WaitWithDefaultTimeout()
+ Expect(results.ExitCode()).To(Equal(0))
+ Expect(results.LineInOutputContains("podman-integrationtest")).To(BeFalse())
+ })
+
+ It("podman network inspect no args", func() {
+ SkipIfRootless()
+ session := podmanTest.Podman([]string{"network", "inspect"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).ToNot(BeZero())
+ })
+
+ It("podman network inspect", func() {
+ SkipIfRootless()
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "inspect", "podman-integrationtest", "podman"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.IsJSONOutputValid()).To(BeTrue())
+ })
+
+})
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index 455f60937..c61131078 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ "github.com/containers/libpod/pkg/cgroups"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -25,6 +26,17 @@ var _ = Describe("Podman pause", func() {
if err != nil {
os.Exit(1)
}
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ _, err := os.Stat("/sys/fs/cgroup/cgroup.freeze")
+ if err != nil {
+ Skip("freezer controller not available on the current kernel")
+ }
+ }
+
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
podmanTest.SeedImages()
diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go
index 87f89b1dd..4be9da3d2 100644
--- a/test/e2e/run_cpu_test.go
+++ b/test/e2e/run_cpu_test.go
@@ -3,8 +3,10 @@
package integration
import (
+ "io/ioutil"
"os"
+ "github.com/containers/libpod/pkg/cgroups"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -22,6 +24,16 @@ var _ = Describe("Podman run cpu", func() {
if err != nil {
os.Exit(1)
}
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ if err := ioutil.WriteFile("/sys/fs/cgroup/cgroup.subtree_control", []byte("+cpuset"), 0644); err != nil {
+ Skip("cpuset controller not available on the current kernel")
+ }
+ }
+
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
podmanTest.SeedImages()
@@ -36,44 +48,96 @@ var _ = Describe("Podman run cpu", func() {
It("podman run cpu-period", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var result *PodmanSessionIntegration
+ if cgroupsv2 {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"})
+ } else {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpu-period=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"})
+ }
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
- Expect(result.OutputToString()).To(Equal("5000"))
+ Expect(result.LineInOutputContains("5000"))
})
It("podman run cpu-quota", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var result *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"})
+ } else {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
+ }
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
- Expect(result.OutputToString()).To(Equal("5000"))
+ Expect(result.LineInOutputContains("5000"))
})
It("podman run cpus", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"})
- result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Equal(0))
- Expect(result.OutputToString()).To(Equal("100000"))
- result = podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
- result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Equal(0))
- Expect(result.OutputToString()).To(Equal("50000"))
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpu-quota=5000", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.max"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal("5000 100000"))
+ } else {
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_period_us"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal("100000"))
+
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpus=0.5", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal("50000"))
+ }
})
It("podman run cpu-shares", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=2", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.shares"})
- result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Equal(0))
- Expect(result.OutputToString()).To(Equal("2"))
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ // [2-262144] is mapped to [1-10000]
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=262144", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpu.weight"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal("10000"))
+ } else {
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpu-shares=2", ALPINE, "cat", "/sys/fs/cgroup/cpu/cpu.shares"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal("2"))
+ }
})
It("podman run cpuset-cpus", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.cpus"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var result *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.cpus.effective"})
+ } else {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-cpus=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.cpus"})
+ }
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(Equal("0"))
@@ -81,7 +145,17 @@ var _ = Describe("Podman run cpu", func() {
It("podman run cpuset-mems", func() {
SkipIfRootless()
- result := podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.mems"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var result *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/cpuset.mems.effective"})
+ } else {
+ result = podmanTest.Podman([]string{"run", "--rm", "--cpuset-mems=0", ALPINE, "cat", "/sys/fs/cgroup/cpuset/cpuset.mems"})
+ }
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(Equal("0"))
diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go
index 8fe90c8d8..a45735a8a 100644
--- a/test/e2e/run_memory_test.go
+++ b/test/e2e/run_memory_test.go
@@ -5,6 +5,7 @@ package integration
import (
"os"
+ "github.com/containers/libpod/pkg/cgroups"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -36,7 +37,16 @@ var _ = Describe("Podman run memory", func() {
})
It("podman run memory test", func() {
- session := podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"})
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.max"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--memory=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"})
+ }
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("41943040"))
@@ -46,13 +56,31 @@ var _ = Describe("Podman run memory", func() {
if podmanTest.Host.Distribution == "ubuntu" {
Skip("Unable to perform test on Ubuntu distributions due to memory management")
}
- session := podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.high"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--memory-reservation=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"})
+ }
+
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("41943040"))
})
It("podman run memory-swappiness test", func() {
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ Skip("Memory swappiness not supported on cgroups v2")
+ }
+
session := podmanTest.Podman([]string{"run", "--memory-swappiness=15", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.swappiness"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -60,6 +88,12 @@ var _ = Describe("Podman run memory", func() {
})
It("podman run kernel-memory test", func() {
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if cgroupsv2 {
+ Skip("Kernel memory not supported on cgroups v2")
+ }
session := podmanTest.Podman([]string{"run", "--kernel-memory=40m", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 1420a8403..ce2044a72 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -13,6 +13,7 @@ import (
"syscall"
"time"
+ "github.com/containers/libpod/pkg/cgroups"
. "github.com/containers/libpod/test/utils"
"github.com/containers/storage/pkg/stringid"
"github.com/mrunalp/fileutils"
@@ -263,9 +264,15 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("1024"))
- session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"})
- session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(0))
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if !cgroupsv2 {
+ // --oom-kill-disable not supported on cgroups v2.
+ session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ }
session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=100", fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
session.WaitWithDefaultTimeout()
@@ -310,18 +317,43 @@ var _ = Describe("Podman run", func() {
It("podman run blkio-weight test", func() {
SkipIfRootless()
- if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
- Skip("Kernel does not support blkio.weight")
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ if !cgroupsv2 {
+ if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
+ Skip("Kernel does not support blkio.weight")
+ }
+ }
+
+ if cgroupsv2 {
+ // convert linearly from [10-1000] to [1-10000]
+ session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.bfq.weight"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("51"))
+ } else {
+ session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("15"))
}
- session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"})
- session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("15"))
})
It("podman run device-read-bps test", func() {
SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
+ }
+
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("1048576"))
@@ -329,7 +361,17 @@ var _ = Describe("Podman run", func() {
It("podman run device-write-bps test", func() {
SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
+ }
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("1048576"))
@@ -337,7 +379,18 @@ var _ = Describe("Podman run", func() {
It("podman run device-read-iops test", func() {
SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
+ }
+
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("100"))
@@ -345,7 +398,18 @@ var _ = Describe("Podman run", func() {
It("podman run device-write-iops test", func() {
SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+
+ var session *PodmanSessionIntegration
+
+ if cgroupsv2 {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
+ } else {
+ session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
+ }
+
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("100"))
diff --git a/version/version.go b/version/version.go
index d5f91210e..f0823f260 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.5.1-dev"
+const Version = "1.5.2-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility