diff options
31 files changed, 145 insertions, 48 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index c36479836..5a9dbcb54 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -349,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: @@ -362,21 +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}' @@ -387,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 @@ -1503,6 +1503,8 @@ publish [?[]string](#?[]string) publishAll [?bool](#?bool) +pull [?string](#?string) + quiet [?bool](#?bool) readonly [?bool](#?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/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index ee9e57966..a133549ea 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -15,25 +15,30 @@ import ( // GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, true, false) + return getRuntime(ctx, c, false, true, false, true) +} + +// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify +func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { + return getRuntime(ctx, c, false, false, false, false) } // GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, true, false, false) + return getRuntime(ctx, c, true, false, false, true) } // GetRuntime generates a new libpod runtime configured by command line options func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, false, false) + return getRuntime(ctx, c, false, false, false, true) } // GetRuntimeNoStore generates a new libpod runtime configured by command line options func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, false, true) + return getRuntime(ctx, c, false, false, true, true) } -func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore bool) (*libpod.Runtime, error) { +func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool) (*libpod.Runtime, error) { options := []libpod.RuntimeOption{} storageOpts := storage.StoreOptions{} storageSet := false @@ -165,6 +170,10 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra infraCommand, _ := c.Flags().GetString("infra-command") options = append(options, libpod.WithDefaultInfraCommand(infraCommand)) } + + if withFDS { + options = append(options, libpod.WithEnableSDNotify()) + } if c.Flags().Changed("config") { return libpod.NewRuntimeFromConfig(ctx, c.GlobalFlags.Config, options...) } 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.go b/cmd/podman/varlink.go index 92315cd6b..5f89534be 100644 --- a/cmd/podman/varlink.go +++ b/cmd/podman/varlink.go @@ -79,7 +79,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error { timeout := time.Duration(c.Timeout) * time.Millisecond // Create a single runtime for varlink - runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) + runtime, err := libpodruntime.GetRuntimeDisableFDs(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } 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/completions/bash/podman b/completions/bash/podman index cf9b31393..962c15a95 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1845,6 +1845,7 @@ _podman_container_run() { --pids-limit --pod --publish -p + --pull --runtime --rootfs --security-opt 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/docs/podman-create.1.md b/docs/podman-create.1.md index 6fe224bd4..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 diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 4f6c3568b..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 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/oci.go b/libpod/oci.go index 2eb004b84..4ba3114e3 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -60,6 +60,7 @@ type OCIRuntime struct { noPivot bool reservePorts bool supportsJSON bool + sdNotify bool } // ociError is used to parse the OCI runtime JSON log. It is not part of the @@ -87,6 +88,7 @@ func newOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *R runtime.logSizeMax = runtimeCfg.MaxLogSize runtime.noPivot = runtimeCfg.NoPivotRoot runtime.reservePorts = runtimeCfg.EnablePortReservation + runtime.sdNotify = runtimeCfg.SDNotify // TODO: probe OCI runtime for feature and enable automatically if // available. diff --git a/libpod/oci_internal_linux.go b/libpod/oci_internal_linux.go index e2c73f5ed..6e4ee2cf2 100644 --- a/libpod/oci_internal_linux.go +++ b/libpod/oci_internal_linux.go @@ -247,10 +247,14 @@ func (r *OCIRuntime) configureConmonEnv(runtimeDir string) ([]string, []*os.File if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok { env = append(env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify)) } - if listenfds, ok := os.LookupEnv("LISTEN_FDS"); ok { - env = append(env, fmt.Sprintf("LISTEN_FDS=%s", listenfds), "LISTEN_PID=1") - fds := activation.Files(false) - extraFiles = append(extraFiles, fds...) + if !r.sdNotify { + if listenfds, ok := os.LookupEnv("LISTEN_FDS"); ok { + env = append(env, fmt.Sprintf("LISTEN_FDS=%s", listenfds), "LISTEN_PID=1") + fds := activation.Files(false) + extraFiles = append(extraFiles, fds...) + } + } else { + logrus.Debug("disabling SD notify") } return env, extraFiles, nil } diff --git a/libpod/options.go b/libpod/options.go index bce07f301..d2a67e38c 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -482,6 +482,15 @@ func WithEventsLogger(logger string) RuntimeOption { } } +// WithEnableSDNotify sets a runtime option so we know whether to disable socket/FD +// listening +func WithEnableSDNotify() RuntimeOption { + return func(rt *Runtime) error { + rt.config.SDNotify = true + return nil + } +} + // Container Creation Options // WithShmDir sets the directory that should be mounted on /dev/shm. diff --git a/libpod/runtime.go b/libpod/runtime.go index 8a4eee081..2fa8dd424 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -252,6 +252,10 @@ type RuntimeConfig struct { EventsLogFilePath string `toml:"-events_logfile_path"` //DetachKeys is the sequence of keys used to detach a container DetachKeys string `toml:"detach_keys"` + + // SDNotify tells Libpod to allow containers to notify the host + // systemd of readiness using the SD_NOTIFY mechanism + SDNotify bool } // runtimeConfiguredFrom is a struct used during early runtime init to help diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 7cfce8919..ad6662f03 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" @@ -111,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/pods.go b/pkg/adapter/pods.go index 87092b458..ded805de2 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" @@ -588,7 +589,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 c80d5991e..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 } 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/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/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))) + }) }) |