Skip to content

Podman pull - add policy flag #26478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions cmd/podman/images/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/containers/buildah/pkg/cli"
"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v5/cmd/podman/common"
"github.com/containers/podman/v5/cmd/podman/registry"
Expand All @@ -25,6 +26,7 @@ type pullOptionsWrapper struct {
TLSVerifyCLI bool // CLI only
CredentialsCLI string
DecryptionKeys []string
PolicyCLI string
}

var (
Expand Down Expand Up @@ -101,6 +103,11 @@ func pullFlags(cmd *cobra.Command) {
flags.String(platformFlagName, "", "Specify the platform for selecting the image. (Conflicts with arch and os)")
_ = cmd.RegisterFlagCompletionFunc(platformFlagName, completion.AutocompleteNone)

policyFlagName := "policy"
// Explicitly set the default to "always" to avoid the default being "missing"
flags.StringVar(&pullOptions.PolicyCLI, policyFlagName, "always", `Pull image policy ("always"|"missing"|"never"|"newer")`)
_ = cmd.RegisterFlagCompletionFunc(policyFlagName, common.AutocompletePullOption)

flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP")
flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
Expand Down Expand Up @@ -143,6 +150,12 @@ func imagePull(cmd *cobra.Command, args []string) error {
pullOptions.SkipTLSVerify = types.NewOptionalBool(!pullOptions.TLSVerifyCLI)
}

pullPolicy, err := config.ParsePullPolicy(pullOptions.PolicyCLI)
if err != nil {
return err
}
pullOptions.PullPolicy = pullPolicy

if cmd.Flags().Changed("retry") {
retry, err := cmd.Flags().GetUint("retry")
if err != nil {
Expand Down
31 changes: 31 additions & 0 deletions docs/source/markdown/podman-pull.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ Print the usage statement.

@@option platform

#### **--policy**

Pull image policy. The default is **always**.

- `always`: Always pull the image and throw an error if the pull fails.
- `missing`: Only pull the image if it could not be found in the local containers storage. Throw an error if no image could be found and the pull fails.
- `never`: Never pull the image; only use the local version. Throw an error if the image is not present locally.
- `newer`: Pull if the image on the registry is newer than the one in the local containers storage. An image is considered to be newer when the digests are different. Comparing the time stamps is prone to errors. Pull errors are suppressed if a local image was found.

#### **--quiet**, **-q**

Suppress output information when pulling images
Expand Down Expand Up @@ -215,6 +224,28 @@ $ podman --remote pull -q --retry 6 --retry-delay 10s ubi9
4d6addf62a90e392ff6d3f470259eb5667eab5b9a8e03d20b41d0ab910f92170
```

Pull an image only if not present locally.
```
$ podman pull --policy missing alpine:latest
```

Never pull the image, only use local version.
```
$ podman pull --policy never alpine:latest
```

Always pull the image even if present locally.
```
$ podman pull --policy always alpine:latest
Trying to pull docker.io/library/alpine:latest...
Getting image source signatures
Copying blob 5843afab3874 done
Copying config d4ff818577 done
Writing manifest to image destination
Storing signatures
d4ff818577bc193b309b355b02ebc9220427090057b54a59e73b79bdfe139b83
```

## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-push(1)](podman-push.1.md)**, **[podman-login(1)](podman-login.1.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)**, **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**

Expand Down
60 changes: 60 additions & 0 deletions test/system/156-pull-policy.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
load helpers
load helpers.network
load helpers.registry

function setup() {
skip_if_remote "tests depend on start_registry which does not work with podman-remote"

basic_setup
start_registry
}

@test "podman pull with policy flag" {
local registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
local image_for_test=$registry/i-$(safename):$(random_string)
local authfile=$PODMAN_TMPDIR/authfile.json

run_podman login --authfile=$authfile \
--tls-verify=false \
--username ${PODMAN_LOGIN_USER} \
--password ${PODMAN_LOGIN_PASS} \
$registry

# Generate a test image and push it to the registry.
# For safety in parallel runs, test image must be isolated
# from $IMAGE. A simple add-tag will not work. (#23756)
run_podman create -q $IMAGE true
local tmpcid=$output
run_podman commit -q $tmpcid $image_for_test
local image_id=$output
run_podman rm $tmpcid
run_podman image push --tls-verify=false --authfile=$authfile $image_for_test
# Remove the local image to make sure it will be pulled again
run_podman image rm --ignore $image_for_test

# Test invalid policy
run_podman 125 pull --tls-verify=false --authfile $authfile --policy invalid $image_for_test
assert "$output" = "Error: unsupported pull policy \"invalid\""

# Test policy=never with image not present
run_podman 125 pull --tls-verify=false --authfile $authfile --policy never $image_for_test
assert "$output" = "Error: $image_for_test: image not known"

# Test policy=missing with image not present (should succeed)
run_podman pull --tls-verify=false --authfile $authfile --policy missing $image_for_test
assert "$output" =~ "Writing manifest to image destination"

# Test policy=missing with image present (should not pull again)
run_podman pull --tls-verify=false --authfile $authfile --policy missing $image_for_test
assert "$output" = $image_id

# Test policy=always (should always pull)
run_podman pull --tls-verify=false --authfile $authfile --policy always $image_for_test
assert "$output" =~ "Writing manifest to image destination"

# Test policy=newer with image present and no new image(should not pull again)
run_podman pull --tls-verify=false --authfile $authfile --policy newer $image_for_test
assert "$output" = $image_id

run_podman image rm --ignore $image_for_test
}