mirror of
https://github.com/containers/podman.git
synced 2025-06-25 03:52:15 +08:00
Merge pull request #10937 from vrothberg/auto-update
auto-update: add --dry-run
This commit is contained in:
@ -53,6 +53,8 @@ func init() {
|
|||||||
flags.StringVar(&autoUpdateOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path to the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
flags.StringVar(&autoUpdateOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path to the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||||
_ = autoUpdateCommand.RegisterFlagCompletionFunc(authfileFlagName, completion.AutocompleteDefault)
|
_ = autoUpdateCommand.RegisterFlagCompletionFunc(authfileFlagName, completion.AutocompleteDefault)
|
||||||
|
|
||||||
|
flags.BoolVar(&autoUpdateOptions.DryRun, "dry-run", false, "Check for pending updates")
|
||||||
|
|
||||||
flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template")
|
flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template")
|
||||||
_ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(autoUpdateOutput{}))
|
_ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(autoUpdateOutput{}))
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,11 @@ If the authorization state is not found there, `$HOME/.docker/config.json` is ch
|
|||||||
|
|
||||||
Note: There is also the option to override the default path of the authentication file by setting the `REGISTRY_AUTH_FILE` environment variable. This can be done with **export REGISTRY_AUTH_FILE=_path_**.
|
Note: There is also the option to override the default path of the authentication file by setting the `REGISTRY_AUTH_FILE` environment variable. This can be done with **export REGISTRY_AUTH_FILE=_path_**.
|
||||||
|
|
||||||
|
#### **--dry-run**=*true|false*
|
||||||
|
|
||||||
|
Check for the availability of new images but do not perform any pull operation or restart any service or container.
|
||||||
|
The `UPDATED` field indicates the availability of a new image with "pending".
|
||||||
|
|
||||||
#### **--format**=*format*
|
#### **--format**=*format*
|
||||||
|
|
||||||
Change the default output format. This can be of a supported type like 'json' or a Go template.
|
Change the default output format. This can be of a supported type like 'json' or a Go template.
|
||||||
@ -64,7 +69,7 @@ Autoupdate with registry policy
|
|||||||
### Start a container
|
### Start a container
|
||||||
$ podman run --label "io.containers.autoupdate=registry" \
|
$ podman run --label "io.containers.autoupdate=registry" \
|
||||||
--label "io.containers.autoupdate.authfile=/some/authfile.json" \
|
--label "io.containers.autoupdate.authfile=/some/authfile.json" \
|
||||||
-d busybox:latest top
|
-d --name=test registry.fedoraproject.org/fedora:latest sleep infinity
|
||||||
bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
||||||
|
|
||||||
### Generate a systemd unit for this container
|
### Generate a systemd unit for this container
|
||||||
@ -72,18 +77,23 @@ $ podman generate systemd --new --files bc219740a210455fa27deacc96d50a9e20516492
|
|||||||
/home/user/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
|
/home/user/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
|
||||||
|
|
||||||
### Load the new systemd unit and start it
|
### Load the new systemd unit and start it
|
||||||
$ mv ./container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service ~/.config/systemd/user
|
$ mv ./container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service ~/.config/systemd/user/container-test.service
|
||||||
$ systemctl --user daemon-reload
|
$ systemctl --user daemon-reload
|
||||||
|
|
||||||
### If the previously created containers or pods are using shared resources, such as ports, make sure to remove them before starting the generated systemd units.
|
### If the previously created containers or pods are using shared resources, such as ports, make sure to remove them before starting the generated systemd units.
|
||||||
$ podman stop bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
$ podman stop bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
||||||
$ podman rm bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
$ podman rm bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
|
||||||
|
|
||||||
$ systemctl --user start container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
|
$ systemctl --user start container-test.service
|
||||||
|
|
||||||
### Auto-update the container
|
### Check if a newer image is available
|
||||||
|
$ podman auto-update --dry-run --format "{{.Image}} {{.Updated}}"
|
||||||
|
registry.fedoraproject.org/fedora:latest pending
|
||||||
|
|
||||||
|
### Autoupdate the services
|
||||||
$ podman auto-update
|
$ podman auto-update
|
||||||
[...]
|
UNIT CONTAINER IMAGE POLICY UPDATED
|
||||||
|
container-test.service 08fd34e533fd (test) registry.fedoraproject.org/fedora:latest registry false
|
||||||
```
|
```
|
||||||
|
|
||||||
Autoupdate with local policy
|
Autoupdate with local policy
|
||||||
|
@ -75,12 +75,6 @@ func LookupPolicy(s string) (Policy, error) {
|
|||||||
return "", errors.Errorf("invalid auto-update policy %q: valid policies are %+q", s, keys)
|
return "", errors.Errorf("invalid auto-update policy %q: valid policies are %+q", s, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options include parameters for auto updates.
|
|
||||||
type Options struct {
|
|
||||||
// Authfile to use when contacting registries.
|
|
||||||
Authfile string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateImageReference checks if the specified imageName is a fully-qualified
|
// ValidateImageReference checks if the specified imageName is a fully-qualified
|
||||||
// image reference to the docker transport (without digest). Such a reference
|
// image reference to the docker transport (without digest). Such a reference
|
||||||
// includes a domain, name and tag (e.g., quay.io/podman/stable:latest). The
|
// includes a domain, name and tag (e.g., quay.io/podman/stable:latest). The
|
||||||
@ -120,7 +114,7 @@ func ValidateImageReference(imageName string) error {
|
|||||||
//
|
//
|
||||||
// It returns a slice of successfully restarted systemd units and a slice of
|
// It returns a slice of successfully restarted systemd units and a slice of
|
||||||
// errors encountered during auto update.
|
// errors encountered during auto update.
|
||||||
func AutoUpdate(ctx context.Context, runtime *libpod.Runtime, options Options) ([]*entities.AutoUpdateReport, []error) {
|
func AutoUpdate(ctx context.Context, runtime *libpod.Runtime, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
|
||||||
// Create a map from `image ID -> []*Container`.
|
// Create a map from `image ID -> []*Container`.
|
||||||
containerMap, errs := imageContainersMap(runtime)
|
containerMap, errs := imageContainersMap(runtime)
|
||||||
if len(containerMap) == 0 {
|
if len(containerMap) == 0 {
|
||||||
@ -183,7 +177,7 @@ func AutoUpdate(ctx context.Context, runtime *libpod.Runtime, options Options) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// autoUpdateRegistry updates the image/container according to the "registry" policy.
|
// autoUpdateRegistry updates the image/container according to the "registry" policy.
|
||||||
func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod.Container, updatedRawImages map[string]bool, options *Options, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
|
func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod.Container, updatedRawImages map[string]bool, options *entities.AutoUpdateOptions, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
|
||||||
cid := ctr.ID()
|
cid := ctr.ID()
|
||||||
rawImageName := ctr.RawImageName()
|
rawImageName := ctr.RawImageName()
|
||||||
if rawImageName == "" {
|
if rawImageName == "" {
|
||||||
@ -225,6 +219,11 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod.
|
|||||||
return report, nil
|
return report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.DryRun {
|
||||||
|
report.Updated = "pending"
|
||||||
|
return report, nil
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := updateImage(ctx, runtime, rawImageName, options); err != nil {
|
if _, err := updateImage(ctx, runtime, rawImageName, options); err != nil {
|
||||||
return report, errors.Wrapf(err, "error registry auto-updating container %q: image update for %q failed", cid, rawImageName)
|
return report, errors.Wrapf(err, "error registry auto-updating container %q: image update for %q failed", cid, rawImageName)
|
||||||
}
|
}
|
||||||
@ -240,7 +239,7 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// autoUpdateRegistry updates the image/container according to the "local" policy.
|
// autoUpdateRegistry updates the image/container according to the "local" policy.
|
||||||
func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.Container, options *Options, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
|
func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.Container, options *entities.AutoUpdateOptions, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
|
||||||
cid := ctr.ID()
|
cid := ctr.ID()
|
||||||
rawImageName := ctr.RawImageName()
|
rawImageName := ctr.RawImageName()
|
||||||
if rawImageName == "" {
|
if rawImageName == "" {
|
||||||
@ -272,6 +271,11 @@ func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.C
|
|||||||
return report, nil
|
return report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.DryRun {
|
||||||
|
report.Updated = "pending"
|
||||||
|
return report, nil
|
||||||
|
}
|
||||||
|
|
||||||
logrus.Infof("Auto-updating container %q using local image %q", cid, rawImageName)
|
logrus.Infof("Auto-updating container %q using local image %q", cid, rawImageName)
|
||||||
if err := restartSystemdUnit(ctr, unit, conn); err != nil {
|
if err := restartSystemdUnit(ctr, unit, conn); err != nil {
|
||||||
return report, err
|
return report, err
|
||||||
@ -346,7 +350,7 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string]policyMapper, []err
|
|||||||
|
|
||||||
// getAuthfilePath returns an authfile path, if set. The authfile label in the
|
// getAuthfilePath returns an authfile path, if set. The authfile label in the
|
||||||
// container, if set, as precedence over the one set in the options.
|
// container, if set, as precedence over the one set in the options.
|
||||||
func getAuthfilePath(ctr *libpod.Container, options *Options) string {
|
func getAuthfilePath(ctr *libpod.Container, options *entities.AutoUpdateOptions) string {
|
||||||
labels := ctr.Labels()
|
labels := ctr.Labels()
|
||||||
authFilePath, exists := labels[AuthfileLabel]
|
authFilePath, exists := labels[AuthfileLabel]
|
||||||
if exists {
|
if exists {
|
||||||
@ -375,7 +379,7 @@ func newerLocalImageAvailable(runtime *libpod.Runtime, img *libimage.Image, rawI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateImage pulls the specified image.
|
// updateImage pulls the specified image.
|
||||||
func updateImage(ctx context.Context, runtime *libpod.Runtime, name string, options *Options) (*libimage.Image, error) {
|
func updateImage(ctx context.Context, runtime *libpod.Runtime, name string, options *entities.AutoUpdateOptions) (*libimage.Image, error) {
|
||||||
pullOptions := &libimage.PullOptions{}
|
pullOptions := &libimage.PullOptions{}
|
||||||
pullOptions.AuthFilePath = options.Authfile
|
pullOptions.AuthFilePath = options.Authfile
|
||||||
pullOptions.Writer = os.Stderr
|
pullOptions.Writer = os.Stderr
|
||||||
|
@ -4,6 +4,10 @@ package entities
|
|||||||
type AutoUpdateOptions struct {
|
type AutoUpdateOptions struct {
|
||||||
// Authfile to use when contacting registries.
|
// Authfile to use when contacting registries.
|
||||||
Authfile string
|
Authfile string
|
||||||
|
// Only check for but do not perform any update. If an update is
|
||||||
|
// pending, it will be indicated in the Updated field of
|
||||||
|
// AutoUpdateReport.
|
||||||
|
DryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoUpdateReport contains the results from running auto-update.
|
// AutoUpdateReport contains the results from running auto-update.
|
||||||
@ -18,7 +22,7 @@ type AutoUpdateReport struct {
|
|||||||
Policy string
|
Policy string
|
||||||
// SystemdUnit running a container configured for auto updates.
|
// SystemdUnit running a container configured for auto updates.
|
||||||
SystemdUnit string
|
SystemdUnit string
|
||||||
// Indicates whether the image was updated and the container (and
|
// Indicates the update status: true, false, failed, pending (see
|
||||||
// systemd unit) restarted.
|
// DryRun).
|
||||||
Updated string
|
Updated string
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
|
func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
|
||||||
// Convert the entities options to the autoupdate ones. We can't use
|
return autoupdate.AutoUpdate(ctx, ic.Libpod, options)
|
||||||
// them in the entities package as low-level packages must not leak
|
|
||||||
// into the remote client.
|
|
||||||
autoOpts := autoupdate.Options{Authfile: options.Authfile}
|
|
||||||
return autoupdate.AutoUpdate(ctx, ic.Libpod, autoOpts)
|
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,9 @@ function _confirm_update() {
|
|||||||
generate_service alpine image
|
generate_service alpine image
|
||||||
|
|
||||||
_wait_service_ready container-$cname.service
|
_wait_service_ready container-$cname.service
|
||||||
|
run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
||||||
|
is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,pending,registry.*" "Image update is pending."
|
||||||
|
|
||||||
run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
||||||
is "$output" "Trying to pull.*" "Image is updated."
|
is "$output" "Trying to pull.*" "Image is updated."
|
||||||
is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,true,registry.*" "Image is updated."
|
is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,true,registry.*" "Image is updated."
|
||||||
@ -159,6 +162,9 @@ function _confirm_update() {
|
|||||||
imageID="$output"
|
imageID="$output"
|
||||||
|
|
||||||
_wait_service_ready container-$cname.service
|
_wait_service_ready container-$cname.service
|
||||||
|
run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
||||||
|
is "$output" ".*container-$cname.service,quay.io/libpod/localtest:latest,pending,local.*" "Image update is pending."
|
||||||
|
|
||||||
run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
|
||||||
is "$output" ".*container-$cname.service,quay.io/libpod/localtest:latest,true,local.*" "Image is updated."
|
is "$output" ".*container-$cname.service,quay.io/libpod/localtest:latest,true,local.*" "Image is updated."
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user