summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/auto-update.go20
-rw-r--r--completions/bash/podman21
-rw-r--r--docs/source/markdown/podman-auto-update.1.md12
-rw-r--r--pkg/autoupdate/autoupdate.go25
-rw-r--r--pkg/domain/entities/auto-update.go6
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/infra/abi/auto-update.go8
-rw-r--r--pkg/domain/infra/tunnel/auto-update.go2
-rw-r--r--test/system/030-run.bats36
-rw-r--r--test/system/250-systemd.bats39
10 files changed, 129 insertions, 42 deletions
diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go
index 758cbbc6f..11433bc25 100644
--- a/cmd/podman/auto-update.go
+++ b/cmd/podman/auto-update.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
+ "github.com/containers/common/pkg/auth"
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/errorhandling"
@@ -11,16 +12,18 @@ import (
)
var (
+ autoUpdateOptions = entities.AutoUpdateOptions{}
autoUpdateDescription = `Auto update containers according to their auto-update policy.
Auto-update policies are specified with the "io.containers.autoupdate" label.
- Note that this command is experimental.`
+ Note that this command is experimental. Please refer to the podman-auto-update(1) man page for details.`
autoUpdateCommand = &cobra.Command{
- Use: "auto-update [flags]",
- Short: "Auto update containers according to their auto-update policy",
- Long: autoUpdateDescription,
- RunE: autoUpdate,
- Example: `podman auto-update`,
+ Use: "auto-update [flags]",
+ Short: "Auto update containers according to their auto-update policy",
+ Long: autoUpdateDescription,
+ RunE: autoUpdate,
+ Example: `podman auto-update
+ podman auto-update --authfile ~/authfile.json`,
}
)
@@ -29,6 +32,9 @@ func init() {
Mode: []entities.EngineMode{entities.ABIMode},
Command: autoUpdateCommand,
})
+
+ flags := autoUpdateCommand.Flags()
+ flags.StringVar(&autoUpdateOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path to the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
}
func autoUpdate(cmd *cobra.Command, args []string) error {
@@ -36,7 +42,7 @@ func autoUpdate(cmd *cobra.Command, args []string) error {
// Backwards compat. System tests expext this error string.
return errors.Errorf("`%s` takes no arguments", cmd.CommandPath())
}
- report, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext())
+ report, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions)
if report != nil {
for _, unit := range report.Units {
fmt.Println(unit)
diff --git a/completions/bash/podman b/completions/bash/podman
index 1e29a2e30..5dbd179ce 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -702,6 +702,27 @@ __podman_images() {
__podman_q images $images_args | awk "$awk_script" | grep -v '<none>$'
}
+_podman_auto_update() {
+ local options_with_args="
+ --authfile
+ "
+
+ local boolean_options="
+ --help
+ -h
+ "
+
+ _complete_ "$options_with_args" "$boolean_options"
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ *)
+ __podman_complete_volume_names
+ ;;
+ esac
+}
+
# __podman_complete_volumes applies completion of volumes based on the current
# value of `$cur` or the value of the optional first option `--cur`, if given.
__podman_complete_volumes() {
diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md
index 93ad22f76..f98b71420 100644
--- a/docs/source/markdown/podman-auto-update.1.md
+++ b/docs/source/markdown/podman-auto-update.1.md
@@ -21,11 +21,21 @@ Note that `podman auto-update` relies on systemd and requires a fully-qualified
This enforcement is necessary to know which image to actually check and pull.
If an image ID was used, Podman would not know which image to check/pull anymore.
+## OPTIONS
+
+**--authfile**=*path*
+
+Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
+If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands)
+
+Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
+environment variable. `export REGISTRY_AUTH_FILE=path`
+
## EXAMPLES
```
# Start a container
-$ podman run -d busybox:latest top
+$ podman run --label "io.containers.autoupdate=image" -d busybox:latest top
bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
# Generate a systemd unit for this container
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 78d5ac474..1b0419892 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -63,6 +63,12 @@ func LookupPolicy(s string) (Policy, error) {
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
// 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
@@ -96,7 +102,7 @@ func ValidateImageReference(imageName string) error {
//
// It returns a slice of successfully restarted systemd units and a slice of
// errors encountered during auto update.
-func AutoUpdate(runtime *libpod.Runtime) ([]string, []error) {
+func AutoUpdate(runtime *libpod.Runtime, options Options) ([]string, []error) {
// Create a map from `image ID -> []*Container`.
containerMap, errs := imageContainersMap(runtime)
if len(containerMap) == 0 {
@@ -138,7 +144,7 @@ func AutoUpdate(runtime *libpod.Runtime) ([]string, []error) {
if rawImageName == "" {
errs = append(errs, errors.Errorf("error auto-updating container %q: raw-image name is empty", ctr.ID()))
}
- needsUpdate, err := newerImageAvailable(runtime, image, rawImageName)
+ needsUpdate, err := newerImageAvailable(runtime, image, rawImageName, options)
if err != nil {
errs = append(errs, errors.Wrapf(err, "error auto-updating container %q: image check for %q failed", ctr.ID(), rawImageName))
continue
@@ -148,7 +154,7 @@ func AutoUpdate(runtime *libpod.Runtime) ([]string, []error) {
}
logrus.Infof("Auto-updating container %q using image %q", ctr.ID(), rawImageName)
if _, updated := updatedRawImages[rawImageName]; !updated {
- _, err = updateImage(runtime, rawImageName)
+ _, err = updateImage(runtime, rawImageName, options)
if err != nil {
errs = append(errs, errors.Wrapf(err, "error auto-updating container %q: image update for %q failed", ctr.ID(), rawImageName))
continue
@@ -230,13 +236,15 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string][]*libpod.Container
// newerImageAvailable returns true if there corresponding image on the remote
// registry is newer.
-func newerImageAvailable(runtime *libpod.Runtime, img *image.Image, origName string) (bool, error) {
+func newerImageAvailable(runtime *libpod.Runtime, img *image.Image, origName string, options Options) (bool, error) {
remoteRef, err := docker.ParseReference("//" + origName)
if err != nil {
return false, err
}
- remoteImg, err := remoteRef.NewImage(context.Background(), runtime.SystemContext())
+ sys := runtime.SystemContext()
+ sys.AuthFilePath = options.Authfile
+ remoteImg, err := remoteRef.NewImage(context.Background(), sys)
if err != nil {
return false, err
}
@@ -255,25 +263,22 @@ func newerImageAvailable(runtime *libpod.Runtime, img *image.Image, origName str
}
// updateImage pulls the specified image.
-func updateImage(runtime *libpod.Runtime, name string) (*image.Image, error) {
+func updateImage(runtime *libpod.Runtime, name string, options Options) (*image.Image, error) {
sys := runtime.SystemContext()
registryOpts := image.DockerRegistryOptions{}
signaturePolicyPath := ""
- authFilePath := ""
if sys != nil {
registryOpts.OSChoice = sys.OSChoice
registryOpts.ArchitectureChoice = sys.OSChoice
registryOpts.DockerCertPath = sys.DockerCertPath
-
signaturePolicyPath = sys.SignaturePolicyPath
- authFilePath = sys.AuthFilePath
}
newImage, err := runtime.ImageRuntime().New(context.Background(),
docker.Transport.Name()+"://"+name,
signaturePolicyPath,
- authFilePath,
+ options.Authfile,
os.Stderr,
&registryOpts,
image.SigningOptions{},
diff --git a/pkg/domain/entities/auto-update.go b/pkg/domain/entities/auto-update.go
index aef8fc46b..c51158816 100644
--- a/pkg/domain/entities/auto-update.go
+++ b/pkg/domain/entities/auto-update.go
@@ -1,5 +1,11 @@
package entities
+// AutoUpdateOptions are the options for running auto-update.
+type AutoUpdateOptions struct {
+ // Authfile to use when contacting registries.
+ Authfile string
+}
+
// AutoUpdateReport contains the results from running auto-update.
type AutoUpdateReport struct {
// Units - the restarted systemd units during auto-update.
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 719ac3f9e..e77f0758b 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -10,7 +10,7 @@ import (
)
type ContainerEngine interface {
- AutoUpdate(ctx context.Context) (*AutoUpdateReport, []error)
+ AutoUpdate(ctx context.Context, options AutoUpdateOptions) (*AutoUpdateReport, []error)
Config(ctx context.Context) (*config.Config, error)
ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
diff --git a/pkg/domain/infra/abi/auto-update.go b/pkg/domain/infra/abi/auto-update.go
index aa20664b4..9fcc451fd 100644
--- a/pkg/domain/infra/abi/auto-update.go
+++ b/pkg/domain/infra/abi/auto-update.go
@@ -7,7 +7,11 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func (ic *ContainerEngine) AutoUpdate(ctx context.Context) (*entities.AutoUpdateReport, []error) {
- units, failures := autoupdate.AutoUpdate(ic.Libpod)
+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
+ // them in the entities package as low-level packages must not leak
+ // into the remote client.
+ autoOpts := autoupdate.Options{Authfile: options.Authfile}
+ units, failures := autoupdate.AutoUpdate(ic.Libpod, autoOpts)
return &entities.AutoUpdateReport{Units: units}, failures
}
diff --git a/pkg/domain/infra/tunnel/auto-update.go b/pkg/domain/infra/tunnel/auto-update.go
index fac033050..5c2dd360d 100644
--- a/pkg/domain/infra/tunnel/auto-update.go
+++ b/pkg/domain/infra/tunnel/auto-update.go
@@ -7,6 +7,6 @@ import (
"github.com/pkg/errors"
)
-func (ic *ContainerEngine) AutoUpdate(ctx context.Context) (*entities.AutoUpdateReport, []error) {
+func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) (*entities.AutoUpdateReport, []error) {
return nil, []error{errors.New("not implemented")}
}
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index d5d5121f8..ae2e39d6b 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -161,17 +161,31 @@ echo $rand | 0 | $rand
# 'run --conmon-pidfile --cid-file' makes sure we don't regress on these flags.
# Both are critical for systemd units.
@test "podman run --conmon-pidfile --cidfile" {
- pid=$(mktemp)
- cid=$(mktemp)
-
- # CID file exists -> expected to fail.
- run_podman 125 run --rm --conmon-pidfile=$pid --cidfile=$cid $IMAGE ls
-
- rm $pid $cid
- run_podman run --name keepme --conmon-pidfile=$pid --cidfile=$cid --detach $IMAGE sleep infinity
- stat $pid $cid
- run_podman rm -f keepme
- rm $pid $cid
+ pidfile=${PODMAN_TMPDIR}/pidfile
+ cidfile=${PODMAN_TMPDIR}/cidfile
+
+ cname=$(random_string)
+ run_podman run --name $cname \
+ --conmon-pidfile=$pidfile \
+ --cidfile=$cidfile \
+ --detach \
+ $IMAGE sleep infinity
+ cid="$output"
+
+ is "$(< $cidfile)" "$cid" "contents of cidfile == container ID"
+
+ conmon_pid=$(< $pidfile)
+ is "$(readlink /proc/$conmon_pid/exe)" ".*/conmon" \
+ "conmon pidfile (= PID $conmon_pid) points to conmon process"
+
+ # All OK. Kill container.
+ run_podman rm -f $cid
+
+ # Podman must not overwrite existing cid file.
+ # (overwriting conmon-pidfile is OK, so don't test that)
+ run_podman 125 run --cidfile=$cidfile $IMAGE true
+ is "$output" "Error: container id file exists. .* delete $cidfile" \
+ "podman will not overwrite existing cidfile"
}
# vim: filetype=sh
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 902a7cad8..cdac43c1c 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -6,44 +6,65 @@
load helpers
SERVICE_NAME="podman_test_$(random_string)"
+
+SYSTEMCTL="systemctl"
UNIT_DIR="/usr/lib/systemd/system"
+if is_rootless; then
+ UNIT_DIR="$HOME/.config/systemd/user"
+ mkdir -p $UNIT_DIR
+
+ SYSTEMCTL="$SYSTEMCTL --user"
+fi
UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
function setup() {
skip_if_remote
- skip_if_rootless "systemd tests are root-only for now"
basic_setup
}
function teardown() {
+ run '?' $SYSTEMCTL stop "$SERVICE_NAME"
rm -f "$UNIT_FILE"
- systemctl daemon-reload
+ $SYSTEMCTL daemon-reload
basic_teardown
}
+# This test can fail in dev. environment because of SELinux.
+# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate - systemd - basic" {
- run_podman create --name keepme --detach busybox:latest top
+ cname=$(random_string)
+ run_podman create --name $cname --detach $IMAGE top
- run_podman generate systemd --new keepme > "$UNIT_FILE"
- run_podman rm keepme
+ run_podman generate systemd --new $cname
+ echo "$output" > "$UNIT_FILE"
+ run_podman rm $cname
- systemctl daemon-reload
+ $SYSTEMCTL daemon-reload
- run systemctl start "$SERVICE_NAME"
+ run $SYSTEMCTL start "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error starting systemd unit $SERVICE_NAME, output: $output"
fi
- run systemctl status "$SERVICE_NAME"
+ run $SYSTEMCTL status "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Non-zero status of systemd unit $SERVICE_NAME, output: $output"
fi
- run systemctl stop "$SERVICE_NAME"
+ # Give container time to start; make sure output looks top-like
+ sleep 2
+ run_podman logs $cname
+ is "$output" ".*Load average:.*" "running container 'top'-like output"
+
+ # All good. Stop service, clean up.
+ run $SYSTEMCTL stop "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error stopping systemd unit $SERVICE_NAME, output: $output"
fi
+
+ rm -f "$UNIT_FILE"
+ $SYSTEMCTL daemon-reload
}
# vim: filetype=sh