Skip to content

Commit 1f1618f

Browse files
Merge pull request #26478 from ygalblum/pull-with-policy
Podman pull - add policy flag
2 parents 844ed82 + 5ab4328 commit 1f1618f

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

cmd/podman/images/pull.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/containers/buildah/pkg/cli"
1010
"github.com/containers/common/pkg/auth"
1111
"github.com/containers/common/pkg/completion"
12+
"github.com/containers/common/pkg/config"
1213
"github.com/containers/image/v5/types"
1314
"github.com/containers/podman/v5/cmd/podman/common"
1415
"github.com/containers/podman/v5/cmd/podman/registry"
@@ -25,6 +26,7 @@ type pullOptionsWrapper struct {
2526
TLSVerifyCLI bool // CLI only
2627
CredentialsCLI string
2728
DecryptionKeys []string
29+
PolicyCLI string
2830
}
2931

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

106+
policyFlagName := "policy"
107+
// Explicitly set the default to "always" to avoid the default being "missing"
108+
flags.StringVar(&pullOptions.PolicyCLI, policyFlagName, "always", `Pull image policy ("always"|"missing"|"never"|"newer")`)
109+
_ = cmd.RegisterFlagCompletionFunc(policyFlagName, common.AutocompletePullOption)
110+
104111
flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP")
105112
flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
106113
flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
@@ -143,6 +150,12 @@ func imagePull(cmd *cobra.Command, args []string) error {
143150
pullOptions.SkipTLSVerify = types.NewOptionalBool(!pullOptions.TLSVerifyCLI)
144151
}
145152

153+
pullPolicy, err := config.ParsePullPolicy(pullOptions.PolicyCLI)
154+
if err != nil {
155+
return err
156+
}
157+
pullOptions.PullPolicy = pullPolicy
158+
146159
if cmd.Flags().Changed("retry") {
147160
retry, err := cmd.Flags().GetUint("retry")
148161
if err != nil {

docs/source/markdown/podman-pull.1.md.in

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ Print the usage statement.
6969

7070
@@option platform
7171

72+
#### **--policy**
73+
74+
Pull image policy. The default is **always**.
75+
76+
- `always`: Always pull the image and throw an error if the pull fails.
77+
- `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.
78+
- `never`: Never pull the image; only use the local version. Throw an error if the image is not present locally.
79+
- `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.
80+
7281
#### **--quiet**, **-q**
7382

7483
Suppress output information when pulling images
@@ -215,6 +224,28 @@ $ podman --remote pull -q --retry 6 --retry-delay 10s ubi9
215224
4d6addf62a90e392ff6d3f470259eb5667eab5b9a8e03d20b41d0ab910f92170
216225
```
217226

227+
Pull an image only if not present locally.
228+
```
229+
$ podman pull --policy missing alpine:latest
230+
```
231+
232+
Never pull the image, only use local version.
233+
```
234+
$ podman pull --policy never alpine:latest
235+
```
236+
237+
Always pull the image even if present locally.
238+
```
239+
$ podman pull --policy always alpine:latest
240+
Trying to pull docker.io/library/alpine:latest...
241+
Getting image source signatures
242+
Copying blob 5843afab3874 done
243+
Copying config d4ff818577 done
244+
Writing manifest to image destination
245+
Storing signatures
246+
d4ff818577bc193b309b355b02ebc9220427090057b54a59e73b79bdfe139b83
247+
```
248+
218249
## SEE ALSO
219250
**[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)**
220251

test/system/156-pull-policy.bats

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
load helpers
2+
load helpers.network
3+
load helpers.registry
4+
5+
@test "podman pull with policy flag" {
6+
skip_if_remote "tests depend on start_registry which does not work with podman-remote"
7+
start_registry
8+
9+
local registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
10+
local image_for_test=$registry/i-$(safename):$(random_string)
11+
local authfile=$PODMAN_TMPDIR/authfile.json
12+
13+
run_podman login --authfile=$authfile \
14+
--tls-verify=false \
15+
--username ${PODMAN_LOGIN_USER} \
16+
--password ${PODMAN_LOGIN_PASS} \
17+
$registry
18+
19+
# Generate a test image and push it to the registry.
20+
# For safety in parallel runs, test image must be isolated
21+
# from $IMAGE. A simple add-tag will not work. (#23756)
22+
run_podman create -q $IMAGE true
23+
local tmpcid=$output
24+
run_podman commit -q $tmpcid $image_for_test
25+
local image_id=$output
26+
run_podman rm $tmpcid
27+
run_podman image push --tls-verify=false --authfile=$authfile $image_for_test
28+
# Remove the local image to make sure it will be pulled again
29+
run_podman image rm --ignore $image_for_test
30+
31+
# Test invalid policy
32+
run_podman 125 pull --tls-verify=false --authfile $authfile --policy invalid $image_for_test
33+
assert "$output" = "Error: unsupported pull policy \"invalid\""
34+
35+
# Test policy=never with image not present
36+
run_podman 125 pull --tls-verify=false --authfile $authfile --policy never $image_for_test
37+
assert "$output" = "Error: $image_for_test: image not known"
38+
39+
# Test policy=missing with image not present (should succeed)
40+
run_podman pull --tls-verify=false --authfile $authfile --policy missing $image_for_test
41+
assert "$output" =~ "Writing manifest to image destination"
42+
43+
# Test policy=missing with image present (should not pull again)
44+
run_podman pull --tls-verify=false --authfile $authfile --policy missing $image_for_test
45+
assert "$output" = $image_id
46+
47+
# Test policy=always (should always pull)
48+
run_podman pull --tls-verify=false --authfile $authfile --policy always $image_for_test
49+
assert "$output" =~ "Writing manifest to image destination"
50+
51+
# Test policy=newer with image present and no new image(should not pull again)
52+
run_podman pull --tls-verify=false --authfile $authfile --policy newer $image_for_test
53+
assert "$output" = $image_id
54+
55+
run_podman image rm --ignore $image_for_test
56+
}
57+
58+
@test "podman pull with policy flag - remote" {
59+
# Make sure image is not pulled when policy is never
60+
run_podman 125 pull --policy never quay.io/libpod/i-do-not-exist
61+
assert "$output" = "Error: quay.io/libpod/i-do-not-exist: image not known"
62+
}

0 commit comments

Comments
 (0)