mirror of
https://github.com/containers/podman.git
synced 2025-05-17 23:26:08 +08:00
Merge pull request #3617 from QiWang19/create_pull
add --pull flag for podman create&run
This commit is contained in:
2
API.md
2
API.md
@ -1503,6 +1503,8 @@ publish [?[]string](#?[]string)
|
||||
|
||||
publishAll [?bool](#?bool)
|
||||
|
||||
pull [?string](#?string)
|
||||
|
||||
quiet [?bool](#?bool)
|
||||
|
||||
readonly [?bool](#?bool)
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -347,6 +347,7 @@ type Create (
|
||||
privileged: ?bool,
|
||||
publish: ?[]string,
|
||||
publishAll: ?bool,
|
||||
pull: ?string,
|
||||
quiet: ?bool,
|
||||
readonly: ?bool,
|
||||
readonlytmpfs: ?bool,
|
||||
|
@ -1845,6 +1845,7 @@ _podman_container_run() {
|
||||
--pids-limit
|
||||
--pod
|
||||
--publish -p
|
||||
--pull
|
||||
--runtime
|
||||
--rootfs
|
||||
--security-opt
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user