diff options
30 files changed, 242 insertions, 98 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 22f84d7ec..1458e2cc6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -39,7 +39,7 @@ env: UBUNTU_NAME: "ubuntu-20" PRIOR_UBUNTU_NAME: "ubuntu-19" - _BUILT_IMAGE_SUFFIX: "podman-6439450735542272" + _BUILT_IMAGE_SUFFIX: "podman-6530021898584064" FEDORA_CACHE_IMAGE_NAME: "${FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "${PRIOR_FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "${UBUNTU_NAME}-${_BUILT_IMAGE_SUFFIX}" @@ -59,7 +59,7 @@ env: #### Default to NOT operating in any special-case testing mode #### SPECIALMODE: "none" # don't do anything special - TEST_REMOTE_CLIENT: 'false' # don't test remote client by default + RCLI: 'false' # don't test remote client by default ADD_SECOND_PARTITION: 'false' # will certainly fail inside containers MOD_CONTAINERS_CONF: 'true' # Update containers.conf runtime if required by OS environment @@ -422,8 +422,8 @@ testing_task: env: ADD_SECOND_PARTITION: 'true' matrix: - - TEST_REMOTE_CLIENT: 'true' - - TEST_REMOTE_CLIENT: 'false' + - RCLI: 'true' + - RCLI: 'false' networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh' setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}' @@ -470,8 +470,8 @@ special_testing_rootless_task: ADD_SECOND_PARTITION: 'true' SPECIALMODE: 'rootless' # See docs matrix: - - TEST_REMOTE_CLIENT: 'true' - - TEST_REMOTE_CLIENT: 'false' + - RCLI: 'true' + - RCLI: 'false' timeout_in: 60m @@ -674,8 +674,8 @@ verify_test_built_images_task: env: ADD_SECOND_PARTITION: 'true' matrix: - - TEST_REMOTE_CLIENT: 'true' - - TEST_REMOTE_CLIENT: 'false' + - RCLI: 'true' + - RCLI: 'false' matrix: PACKER_BUILDER_NAME: "${FEDORA_NAME}" PACKER_BUILDER_NAME: "${PRIOR_FEDORA_NAME}" diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index ee0f64d99..043871a8c 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -195,6 +195,7 @@ func sortImages(imageS []*entities.ImageSummary) ([]imageReporter, error) { } else { h.ImageSummary = *e h.Repository = "<none>" + h.Tag = "<none>" imgs = append(imgs, h) } listFlag.readOnly = e.IsReadOnly() @@ -205,27 +206,34 @@ func sortImages(imageS []*entities.ImageSummary) ([]imageReporter, error) { } func tokenRepoTag(ref string) (string, string, error) { - if ref == "<none>:<none>" { return "<none>", "<none>", nil } repo, err := reference.Parse(ref) if err != nil { - return "", "", err + return "<none>", "<none>", err } named, ok := repo.(reference.Named) if !ok { - return ref, "", nil + return ref, "<none>", nil + } + name := named.Name() + if name == "" { + name = "<none>" } tagged, ok := repo.(reference.Tagged) if !ok { - return named.Name(), "", nil + return name, "<none>", nil + } + tag := tagged.Tag() + if tag == "" { + tag = "<none>" } - return named.Name(), tagged.Tag(), nil + return name, tag, nil } diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 9e9011dc9..2aa7267c2 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -6,7 +6,6 @@ import ( "path" "runtime" "runtime/pprof" - "strconv" "strings" "github.com/containers/common/pkg/config" @@ -112,15 +111,6 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { cfg := registry.PodmanConfig() - // Validate --remote and --latest not given on same command - latest := cmd.Flags().Lookup("latest") - if latest != nil { - value, _ := strconv.ParseBool(latest.Value.String()) - if cfg.Remote && value { - return errors.Errorf("For %s \"--remote\" and \"--latest\", are mutually exclusive flags", cmd.CommandPath()) - } - } - // Prep the engines if _, err := registry.NewImageEngine(cmd, args); err != nil { return err diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index a33f47959..aacb41e69 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" + "github.com/containers/podman/v2/cmd/podman/registry" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -47,17 +48,20 @@ func IDOrLatestArgs(cmd *cobra.Command, args []string) error { // CheckAllLatestAndCIDFile checks that --all and --latest are used correctly. // If cidfile is set, also check for the --cidfile flag. func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error { + var specifiedLatest bool argLen := len(args) - if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - if !cidfile { - return errors.New("unable to lookup values for 'latest' or 'all'") - } else if c.Flags().Lookup("cidfile") == nil { - return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") + if !registry.IsRemote() { + specifiedLatest, _ = c.Flags().GetBool("latest") + if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { + if !cidfile { + return errors.New("unable to lookup values for 'latest' or 'all'") + } else if c.Flags().Lookup("cidfile") == nil { + return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") + } } } specifiedAll, _ := c.Flags().GetBool("all") - specifiedLatest, _ := c.Flags().GetBool("latest") specifiedCIDFile := false if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 { specifiedCIDFile = true @@ -98,17 +102,21 @@ func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool // CheckAllLatestAndPodIDFile checks that --all and --latest are used correctly. // If withIDFile is set, also check for the --pod-id-file flag. func CheckAllLatestAndPodIDFile(c *cobra.Command, args []string, ignoreArgLen bool, withIDFile bool) error { + var specifiedLatest bool argLen := len(args) - if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - if !withIDFile { - return errors.New("unable to lookup values for 'latest' or 'all'") - } else if c.Flags().Lookup("pod-id-file") == nil { - return errors.New("unable to lookup values for 'latest', 'all' or 'pod-id-file'") + if !registry.IsRemote() { + // remote clients have no latest flag + specifiedLatest, _ = c.Flags().GetBool("latest") + if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { + if !withIDFile { + return errors.New("unable to lookup values for 'latest' or 'all'") + } else if c.Flags().Lookup("pod-id-file") == nil { + return errors.New("unable to lookup values for 'latest', 'all' or 'pod-id-file'") + } } } specifiedAll, _ := c.Flags().GetBool("all") - specifiedLatest, _ := c.Flags().GetBool("latest") specifiedPodIDFile := false if pid, _ := c.Flags().GetStringArray("pod-id-file"); len(pid) > 0 { specifiedPodIDFile = true diff --git a/cmd/podman/validate/latest.go b/cmd/podman/validate/latest.go index 5c76fe847..c9bff798a 100644 --- a/cmd/podman/validate/latest.go +++ b/cmd/podman/validate/latest.go @@ -7,9 +7,8 @@ import ( func AddLatestFlag(cmd *cobra.Command, b *bool) { // Initialization flag verification - cmd.Flags().BoolVarP(b, "latest", "l", false, - "Act on the latest container podman is aware of\nNot supported with the \"--remote\" flag") - if registry.IsRemote() { - _ = cmd.Flags().MarkHidden("latest") + if !registry.IsRemote() { + cmd.Flags().BoolVarP(b, "latest", "l", false, + "Act on the latest container podman is aware of\nNot supported with the \"--remote\" flag") } } diff --git a/contrib/cirrus/apiv2_test.sh b/contrib/cirrus/apiv2_test.sh index 33e9fbc6b..546fe8e30 100755 --- a/contrib/cirrus/apiv2_test.sh +++ b/contrib/cirrus/apiv2_test.sh @@ -7,7 +7,7 @@ source $(dirname $0)/lib.sh req_env_var GOSRC SCRIPT_BASE OS_RELEASE_ID OS_RELEASE_VER CONTAINER_RUNTIME VARLINK_LOG LOCAL_OR_REMOTE=local -if [[ "$TEST_REMOTE_CLIENT" = "true" ]]; then +if [[ "$RCLI" = "true" ]]; then LOCAL_OR_REMOTE=remote fi diff --git a/contrib/cirrus/build_release.sh b/contrib/cirrus/build_release.sh index 07db88f81..45634f368 100755 --- a/contrib/cirrus/build_release.sh +++ b/contrib/cirrus/build_release.sh @@ -4,11 +4,11 @@ set -e source $(dirname $0)/lib.sh -req_env_var TEST_REMOTE_CLIENT OS_RELEASE_ID GOSRC +req_env_var RCLI OS_RELEASE_ID GOSRC cd $GOSRC -if [[ "$TEST_REMOTE_CLIENT" == "true" ]] && [[ -z "$CROSS_PLATFORM" ]] +if [[ "$RCLI" == "true" ]] && [[ -z "$CROSS_PLATFORM" ]] then CROSS_PLATFORM=linux fi diff --git a/contrib/cirrus/check_image.sh b/contrib/cirrus/check_image.sh index 39c2be3f8..13172fe1c 100755 --- a/contrib/cirrus/check_image.sh +++ b/contrib/cirrus/check_image.sh @@ -6,7 +6,7 @@ source $(dirname $0)/lib.sh EVIL_UNITS="$($CIRRUS_WORKING_DIR/$PACKER_BASE/systemd_banish.sh --list)" -req_env_var PACKER_BUILDER_NAME TEST_REMOTE_CLIENT EVIL_UNITS OS_RELEASE_ID CG_FS_TYPE +req_env_var PACKER_BUILDER_NAME RCLI EVIL_UNITS OS_RELEASE_ID CG_FS_TYPE NFAILS=0 echo "Validating VM image" diff --git a/contrib/cirrus/container_test.sh b/contrib/cirrus/container_test.sh index 8a4ed9492..b56a12232 100644 --- a/contrib/cirrus/container_test.sh +++ b/contrib/cirrus/container_test.sh @@ -18,7 +18,7 @@ if [ "${ID}" != "fedora" ] || [ "${CONTAINER_RUNTIME}" != "" ]; then INTEGRATION_TEST_ENVS="SKIP_USERNS=1" fi -echo "$(date --rfc-3339=seconds) $(basename $0) started with '$*' and TEST_REMOTE_CLIENT='${TEST_REMOTE_CLIENT}'" +echo "$(date --rfc-3339=seconds) $(basename $0) started with '$*' and RCLI='${RCLI}'" pwd @@ -57,9 +57,9 @@ while getopts "bituv" opt; do esac done -# The TEST_REMOTE_CLIENT environment variable decides whether +# The RCLI environment variable decides whether # to test varlinke -if [[ "$TEST_REMOTE_CLIENT" == "true" ]]; then +if [[ "$RCLI" == "true" ]]; then remote=1 fi diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index 692d5a236..c65f5e25f 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -7,7 +7,7 @@ source $(dirname $0)/lib.sh req_env_var GOSRC SCRIPT_BASE OS_RELEASE_ID OS_RELEASE_VER CONTAINER_RUNTIME VARLINK_LOG LOCAL_OR_REMOTE=local -if [[ "$TEST_REMOTE_CLIENT" = "true" ]]; then +if [[ "$RCLI" = "true" ]]; then LOCAL_OR_REMOTE=remote fi diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index d2af4d883..968b2de39 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -96,12 +96,12 @@ LILTO="timeout_attempt_delay_command 120s 5 30s" BIGTO="timeout_attempt_delay_command 300s 5 60s" # Safe env. vars. to transfer from root -> $ROOTLESS_USER (go env handled separately) -ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(TEST_REMOTE.*)' +ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(REMOTE.*)' # Unsafe env. vars for display SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(GC[EP]..+)|(SSH)' SPECIALMODE="${SPECIALMODE:-none}" -TEST_REMOTE_CLIENT="${TEST_REMOTE_CLIENT:-false}" +RCLI="${RCLI:-false}" export CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-podman} # When running as root, this may be empty or not, as a user, it MUST be set. diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh index 0b179591a..859da2966 100755 --- a/contrib/cirrus/logcollector.sh +++ b/contrib/cirrus/logcollector.sh @@ -4,7 +4,7 @@ set -e source $(dirname $0)/lib.sh -req_env_var CIRRUS_WORKING_DIR OS_RELEASE_ID TEST_REMOTE_CLIENT +req_env_var CIRRUS_WORKING_DIR OS_RELEASE_ID RCLI # Assume there are other log collection commands to follow - Don't # let one break another that may be useful, but also keep any @@ -34,12 +34,12 @@ case $1 in journal) showrun journalctl -b ;; podman) showrun ./bin/podman system info ;; varlink) - if [[ "$TEST_REMOTE_CLIENT" == "true" ]] + if [[ "$RCLI" == "true" ]] then echo "(Trailing 100 lines of $VARLINK_LOG)" showrun tail -100 $VARLINK_LOG else - die 0 "\$TEST_REMOTE_CLIENT is not 'true': $TEST_REMOTE_CLIENT" + die 0 "\$RCLI is not 'true': $RCLI" fi ;; packages) diff --git a/contrib/cirrus/packer/fedora_packaging.sh b/contrib/cirrus/packer/fedora_packaging.sh index f19932a9f..4a8f62e45 100644 --- a/contrib/cirrus/packer/fedora_packaging.sh +++ b/contrib/cirrus/packer/fedora_packaging.sh @@ -26,7 +26,7 @@ source /usr/share/automation/environment # Set this to 1 to NOT enable updates-testing repository DISABLE_UPDATES_TESTING=${DISABLE_UPDATES_TESTING:0} -# Do not enable update-stesting on the previous Fedora release +# Do not enable updates-testing on the previous Fedora release if ((DISABLE_UPDATES_TESTING!=0)); then warn "Enabling updates-testing repository for image based on $FEDORA_BASE_IMAGE" $LILTO $SUDO ooe.sh dnf install -y 'dnf-command(config-manager)' @@ -37,7 +37,15 @@ fi $BIGTO ooe.sh $SUDO dnf update -y +# Fedora, as of 31, uses cgroups v2 by default. runc does not support +# cgroups v2, only crun does. (As of 2020-07-30 runc support is +# forthcoming but not even close to ready yet). To ensure a reliable +# runtime environment, force-remove runc if it is present. +# However, because a few other repos. which use these images still need +# it, ensure the runc package is cached in $PACKAGE_DOWNLOAD_DIR so +# it may be swap it in when required. REMOVE_PACKAGES=(runc) + INSTALL_PACKAGES=(\ autoconf automake @@ -118,11 +126,12 @@ INSTALL_PACKAGES=(\ python2 python3-PyYAML python3-dateutil - python3-psutil - python3-pytoml - python3-libsemanage python3-libselinux + python3-libsemanage python3-libvirt + python3-psutil + python3-pytoml + python3-requests redhat-rpm-config rpcbind rsync @@ -163,7 +172,7 @@ $BIGTO ooe.sh $SUDO dnf install -y ${INSTALL_PACKAGES[@]} # $BIGTO ooe.sh $SUDO dnf --enablerepo=updates-testing -y upgrade crun [[ ${#REMOVE_PACKAGES[@]} -eq 0 ]] || \ - $LILTO ooe.sh $SUDO dnf erase -y ${REMOVE_PACKAGES[@]} + $LILTO ooe.sh $SUDO dnf erase -y "${REMOVE_PACKAGES[@]}" if [[ ${#DOWNLOAD_PACKAGES[@]} -gt 0 ]]; then echo "Downloading packages for optional installation at runtime, as needed." @@ -171,8 +180,7 @@ if [[ ${#DOWNLOAD_PACKAGES[@]} -gt 0 ]]; then ooe.sh $SUDO dnf -y module enable cri-o:$(get_kubernetes_version) $SUDO mkdir -p "$PACKAGE_DOWNLOAD_DIR" cd "$PACKAGE_DOWNLOAD_DIR" - $LILTO ooe.sh $SUDO dnf download -y --resolve ${DOWNLOAD_PACKAGES[@]} - ls -la "$PACKAGE_DOWNLOAD_DIR/" + $LILTO ooe.sh $SUDO dnf download -y --resolve "${DOWNLOAD_PACKAGES[@]}" fi echo "Installing runtime tooling" diff --git a/contrib/cirrus/packer/ubuntu_packaging.sh b/contrib/cirrus/packer/ubuntu_packaging.sh index d11c612c5..935e81147 100644 --- a/contrib/cirrus/packer/ubuntu_packaging.sh +++ b/contrib/cirrus/packer/ubuntu_packaging.sh @@ -65,7 +65,7 @@ INSTALL_PACKAGES=(\ gettext git go-md2man - golang + golang-1.14 iproute2 iptables jq @@ -101,12 +101,14 @@ INSTALL_PACKAGES=(\ podman protobuf-c-compiler protobuf-compiler + python-dateutil python-protobuf python2 python3-dateutil python3-pip python3-psutil python3-pytoml + python3-requests python3-setuptools rsync runc @@ -135,6 +137,10 @@ if [[ "$OS_RELEASE_VER" -le 19 ]]; then python-minimal yum-utils ) +else + INSTALL_PACKAGES+=(\ + python-is-python3 + ) fi # Do this at the last possible moment to avoid dpkg lock conflicts @@ -144,22 +150,26 @@ $BIGTO ooe.sh $SUDOAPTGET upgrade echo "Installing general testing and system dependencies" # Necessary to update cache of newly added repos $LILTO ooe.sh $SUDOAPTGET update -$BIGTO ooe.sh $SUDOAPTGET install ${INSTALL_PACKAGES[@]} +$BIGTO ooe.sh $SUDOAPTGET install "${INSTALL_PACKAGES[@]}" if [[ ${#DOWNLOAD_PACKAGES[@]} -gt 0 ]]; then echo "Downloading packages for optional installation at runtime, as needed." $SUDO ln -s /var/cache/apt/archives "$PACKAGE_DOWNLOAD_DIR" - $LILTO ooe.sh $SUDOAPTGET install --download-only ${DOWNLOAD_PACKAGES[@]} - ls -la "$PACKAGE_DOWNLOAD_DIR/" + $LILTO ooe.sh $SUDOAPTGET install --download-only "${DOWNLOAD_PACKAGES[@]}" fi -echo "Installing runtime tooling" -# Save some runtime by having these already available +echo "Configuring Go environment" +# There are multiple (otherwise conflicting) versions of golang available +# on Ubuntu. Being primarily localized by env. vars and defaults, dropping +# a symlink is the appropriate way to "install" a specific version system-wide. +$SUDO ln -sf /usr/lib/go-1.14/bin/go /usr/bin/go +# Initially go was not installed cd $GOSRC -# Required since initially go was not installed -source $GOSRC/$SCRIPT_BASE/lib.sh +source $SCRIPT_BASE/lib.sh echo "Go environment has been setup:" go env + +echo "Building/Installing runtime tooling" $SUDO hack/install_catatonit.sh $SUDO make install.libseccomp.sudo -$SUDO make install.tools +$SUDO make install.tools GO_BUILD='go build' # -mod=vendor breaks this diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index e5f3168da..0b9d686d3 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -39,16 +39,6 @@ done cd "${GOSRC}/" case "${OS_RELEASE_ID}" in ubuntu) - apt-get update - apt-get install -y containers-common - if [[ "$OS_RELEASE_VER" == "19" ]]; then - apt-get purge -y --auto-remove golang* - apt-get install -y golang-1.13 - ln -s /usr/lib/go-1.13/bin/go /usr/bin/go - fi - if [[ "$OS_RELEASE_VER" == "20" ]]; then - apt-get install -y python-is-python3 - fi ;; fedora) # All SELinux distros need this for systemd-in-a-container @@ -113,7 +103,7 @@ case "$SPECIALMODE" in tee -a /etc/environment) && eval "$X" && echo "$X" X=$(echo "export SPECIALMODE='${SPECIALMODE}'" | \ tee -a /etc/environment) && eval "$X" && echo "$X" - X=$(echo "export TEST_REMOTE_CLIENT='${TEST_REMOTE_CLIENT}'" | \ + X=$(echo "export RCLI='${RCLI}'" | \ tee -a /etc/environment) && eval "$X" && echo "$X" setup_rootless fi diff --git a/contrib/cirrus/system_test.sh b/contrib/cirrus/system_test.sh index 33e9fbc6b..546fe8e30 100755 --- a/contrib/cirrus/system_test.sh +++ b/contrib/cirrus/system_test.sh @@ -7,7 +7,7 @@ source $(dirname $0)/lib.sh req_env_var GOSRC SCRIPT_BASE OS_RELEASE_ID OS_RELEASE_VER CONTAINER_RUNTIME VARLINK_LOG LOCAL_OR_REMOTE=local -if [[ "$TEST_REMOTE_CLIENT" = "true" ]]; then +if [[ "$RCLI" = "true" ]]; then LOCAL_OR_REMOTE=remote fi diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 2575f0e86..9dd5ca465 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -424,6 +424,61 @@ func (s *BoltState) SetNamespace(ns string) error { return nil } +// GetName returns the name associated with a given ID. Since IDs are globally +// unique, it works for both containers and pods. +// Returns ErrNoSuchCtr if the ID does not exist. +func (s *BoltState) GetName(id string) (string, error) { + if id == "" { + return "", define.ErrEmptyID + } + + if !s.valid { + return "", define.ErrDBClosed + } + + idBytes := []byte(id) + + db, err := s.getDBCon() + if err != nil { + return "", err + } + defer s.deferredCloseDBCon(db) + + name := "" + + err = db.View(func(tx *bolt.Tx) error { + idBkt, err := getIDBucket(tx) + if err != nil { + return err + } + + nameBytes := idBkt.Get(idBytes) + if nameBytes == nil { + return define.ErrNoSuchCtr + } + + if s.namespaceBytes != nil { + nsBkt, err := getNSBucket(tx) + if err != nil { + return err + } + + idNs := nsBkt.Get(idBytes) + if !bytes.Equal(idNs, s.namespaceBytes) { + return define.ErrNoSuchCtr + } + } + + name = string(nameBytes) + return nil + }) + if err != nil { + return "", err + } + + return name, nil +} + // Container retrieves a single container from the state by its full ID func (s *BoltState) Container(id string) (*Container, error) { if id == "" { diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index 2ac05e88d..0de25a6ef 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -106,6 +106,36 @@ func (s *InMemoryState) SetNamespace(ns string) error { return nil } +// GetName retrieves the name associated with a given ID. +// Works with both Container and Pod IDs. +func (s *InMemoryState) GetName(id string) (string, error) { + if id == "" { + return "", define.ErrEmptyID + } + + var idIndex *truncindex.TruncIndex + if s.namespace != "" { + nsIndex, ok := s.namespaceIndexes[s.namespace] + if !ok { + // We have no containers in the namespace + // Return false + return "", define.ErrNoSuchCtr + } + idIndex = nsIndex.idIndex + } else { + idIndex = s.idIndex + } + + fullID, err := idIndex.Get(id) + if err != nil { + if err == truncindex.ErrNotExist { + return "", define.ErrNoSuchCtr + } + return "", errors.Wrapf(err, "error performing truncindex lookup for ID %s", id) + } + return fullID, nil +} + // Container retrieves a container from its full ID func (s *InMemoryState) Container(id string) (*Container, error) { if id == "" { diff --git a/libpod/runtime.go b/libpod/runtime.go index 3021ef3f4..8a7053e33 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -732,6 +732,22 @@ func (r *Runtime) GetStore() storage.Store { return r.store } +// GetName retrieves the name associated with a given full ID. +// This works for both containers and pods, and does not distinguish between the +// two. +// If the given ID does not correspond to any existing Pod or Container, +// ErrNoSuchCtr is returned. +func (r *Runtime) GetName(id string) (string, error) { + r.lock.RLock() + defer r.lock.RUnlock() + + if !r.valid { + return "", define.ErrRuntimeStopped + } + + return r.state.GetName(id) +} + // DBConfig is a set of Libpod runtime configuration settings that are saved in // a State when it is first created, and can subsequently be retrieved. type DBConfig struct { diff --git a/libpod/state.go b/libpod/state.go index 6206a2994..44632b02f 100644 --- a/libpod/state.go +++ b/libpod/state.go @@ -43,6 +43,12 @@ type State interface { // containers and pods in all namespaces will be returned. SetNamespace(ns string) error + // Resolve an ID into a Name. Since Podman names and IDs are globally + // unique between Pods and Containers, the ID may belong to either a pod + // or container. Despite this, we will always return ErrNoSuchCtr if the + // ID does not exist. + GetName(id string) (string, error) + // Return a container from the database from its full ID. // If the container is not in the set namespace, an error will be // returned. diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 47ea6c40d..e343a9e0c 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -41,7 +41,6 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { Last int `schema:"last"` // alias for limit Limit int `schema:"limit"` Namespace bool `schema:"namespace"` - Pod bool `schema:"pod"` Size bool `schema:"size"` Sync bool `schema:"sync"` }{ @@ -72,7 +71,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { Size: query.Size, Sort: "", Namespace: query.Namespace, - Pod: query.Pod, + Pod: true, Sync: query.Sync, } pss, err := ps.GetContainerLists(runtime, opts) diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index edc1ee3c8..0ad5d29ea 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -661,11 +661,10 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error { // type: boolean // description: Include namespace information // default: false - // - in: query // name: pod // type: boolean // default: false - // description: Include Pod ID and Name if applicable + // description: Ignored. Previously included details on pod name and ID that are currently included by default. // - in: query // name: size // type: boolean diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index 9913b773b..c1eb23233 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -24,7 +24,7 @@ var ( // the most recent number of containers. The pod and size booleans indicate that pod information and rootfs // size information should also be included. Finally, the sync bool synchronizes the OCI runtime and // container state. -func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]entities.ListContainer, error) { // nolint:typecheck +func List(ctx context.Context, filters map[string][]string, all *bool, last *int, size, sync *bool) ([]entities.ListContainer, error) { // nolint:typecheck conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -37,9 +37,6 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int if last != nil { params.Set("limit", strconv.Itoa(*last)) } - if pod != nil { - params.Set("pod", strconv.FormatBool(*pod)) - } if size != nil { params.Set("size", strconv.FormatBool(*size)) } diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index 9a188e5da..db5be4909 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -510,7 +510,7 @@ var _ = Describe("Podman containers ", func() { Expect(err).To(BeNil()) _, err = bt.RunTopContainer(&name2, bindings.PFalse, nil) Expect(err).To(BeNil()) - containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil) + containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil) Expect(err).To(BeNil()) err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM") Expect(err).To(BeNil()) @@ -755,8 +755,23 @@ var _ = Describe("Podman containers ", func() { // Validate list container with id filter filters := make(map[string][]string) filters["id"] = []string{cid} - c, err := containers.List(bt.conn, filters, bindings.PTrue, nil, nil, nil, nil) + c, err := containers.List(bt.conn, filters, bindings.PTrue, nil, nil, nil) Expect(err).To(BeNil()) Expect(len(c)).To(Equal(1)) }) + + It("List containers always includes pod information", func() { + podName := "testpod" + ctrName := "testctr" + bt.Podcreate(&podName) + _, err := bt.RunTopContainer(&ctrName, bindings.PTrue, &podName) + Expect(err).To(BeNil()) + + lastNum := 1 + + c, err := containers.List(bt.conn, nil, bindings.PTrue, &lastNum, nil, nil) + Expect(err).To(BeNil()) + Expect(len(c)).To(Equal(1)) + Expect(c[0].PodName).To(Equal(podName)) + }) }) diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 93c4ede49..0b73ddd7e 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -20,9 +20,10 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, if ctrErr == nil { // Generate the unit for the container. s, err := generate.ContainerUnit(ctr, options) - if err == nil { - return &entities.GenerateSystemdReport{Output: s}, nil + if err != nil { + return nil, err } + return &entities.GenerateSystemdReport{Output: s}, nil } // If it's not a container, we either have a pod or garbage. diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index d2221ab7b..cc919561f 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -496,7 +496,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.ContainerListOptions) ([]entities.ListContainer, error) { - return containers.List(ic.ClientCxt, options.Filters, &options.All, &options.Last, &options.Pod, &options.Size, &options.Sync) + return containers.List(ic.ClientCxt, options.Filters, &options.All, &options.Last, &options.Size, &options.Sync) } func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.ContainerRunOptions) (*entities.ContainerRunReport, error) { diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go index 91a49cd02..0c38a3326 100644 --- a/pkg/domain/infra/tunnel/helpers.go +++ b/pkg/domain/infra/tunnel/helpers.go @@ -20,7 +20,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam if all && len(namesOrIDs) > 0 { return nil, errors.New("cannot lookup containers and all") } - c, err := containers.List(contextWithConnection, nil, bindings.PTrue, nil, nil, nil, bindings.PTrue) + c, err := containers.List(contextWithConnection, nil, bindings.PTrue, nil, nil, bindings.PTrue) if err != nil { return nil, err } diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go index 8163d7247..4c5f60844 100644 --- a/pkg/ps/ps.go +++ b/pkg/ps/ps.go @@ -175,11 +175,14 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities State: conState.String(), } if opts.Pod && len(conConfig.Pod) > 0 { - pod, err := rt.GetPod(conConfig.Pod) + podName, err := rt.GetName(conConfig.Pod) if err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + return entities.ListContainer{}, errors.Wrapf(define.ErrNoSuchPod, "could not find container %s pod (id %s) in state", conConfig.ID, conConfig.Pod) + } return entities.ListContainer{}, err } - ps.PodName = pod.Name() + ps.PodName = podName } if opts.Namespace { diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index d114744c4..60d9162d1 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -53,6 +53,18 @@ var _ = Describe("Podman generate systemd", func() { Expect(session).To(ExitWithError()) }) + It("podman generate systemd bad restart-policy value", func() { + session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"generate", "systemd", "--restart-policy", "bogus", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session).To(ExitWithError()) + found, _ := session.ErrorGrepString("Error: bogus is not a valid restart policy") + Expect(found).Should(BeTrue()) + }) + It("podman generate systemd good timeout value", func() { session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"}) session.WaitWithDefaultTimeout() diff --git a/test/system/120-load.bats b/test/system/120-load.bats index 4825eed07..2fcabcd8a 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -28,8 +28,6 @@ verify_iid_and_name() { @test "podman load - by image ID" { - skip_if_remote "FIXME: pending #7123" - # FIXME: how to build a simple archive instead? get_iid_and_name |