Files
podman/pkg/domain/infra/tunnel/helpers.go
Paul Holzinger 6fce734f42 remote: fix invalid --cidfile + --ignore
When the cidfile does not exists and ignore is set the cli parser skips
the file without error and we call into the backend code without any
names at all. This should logically be a NOP but on remote it caused all
containers to be returned which caused podman stop to stop everything in
this case.

Fixes #23554

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2024-08-12 17:12:12 +02:00

147 lines
4.8 KiB
Go

package tunnel
import (
"context"
"errors"
"fmt"
"github.com/containers/podman/v5/libpod/define"
"github.com/containers/podman/v5/pkg/bindings/containers"
"github.com/containers/podman/v5/pkg/bindings/pods"
"github.com/containers/podman/v5/pkg/domain/entities"
"github.com/containers/podman/v5/pkg/errorhandling"
)
// FIXME: the `ignore` parameter is very likely wrong here as it should rather
//
// be used on *errors* from operations such as remove.
func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) { //nolint:unparam
ctrs, _, err := getContainersAndInputByContext(contextWithConnection, all, ignore, namesOrIDs, nil)
return ctrs, err
}
func getContainersAndInputByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string, filters map[string][]string) ([]entities.ListContainer, []string, error) {
if all && len(namesOrIDs) > 0 {
return nil, nil, errors.New("cannot look up containers and all")
}
// short cut if not all, not filters and no names are given. This can happen with
// --ignore and --cidfile, https://github.com/containers/podman/issues/23554.
// In this case we have to do nothting and not even have to do a request
if !all && len(filters) == 0 && len(namesOrIDs) == 0 {
return nil, nil, nil
}
options := new(containers.ListOptions).WithAll(true).WithSync(true).WithFilters(filters)
allContainers, err := containers.List(contextWithConnection, options)
if err != nil {
return nil, nil, err
}
rawInputs := []string{}
// If no names or IDs are specified, we can return the result as is.
// Otherwise, we need to do some further lookups.
if len(namesOrIDs) == 0 {
for i := range allContainers {
rawInputs = append(rawInputs, allContainers[i].ID)
}
return allContainers, rawInputs, err
}
// Note: it would be nicer if the lists endpoint would support batch
// name/ID lookups as we could use the libpod backend for looking up
// containers rather than risking diverging the local and remote
// lookups.
//
// A `--filter nameOrId=abc` that can be specified multiple times would
// be awesome to have.
filtered := []entities.ListContainer{}
for _, nameOrID := range namesOrIDs {
// First determine if the container exists by doing an inspect.
// Inspect takes supports names and IDs and let's us determine
// a container's full ID.
inspectData, err := containers.Inspect(contextWithConnection, nameOrID, new(containers.InspectOptions).WithSize(false))
if err != nil {
if ignore && errorhandling.Contains(err, define.ErrNoSuchCtr) {
continue
}
return nil, nil, err
}
// Now we can do a full match of the ID to find the right
// container. Note that we *really* need a full ID match to
// prevent any ambiguities between IDs and names (see #7837).
found := false
for _, ctr := range allContainers {
if ctr.ID == inspectData.ID {
filtered = append(filtered, ctr)
rawInputs = append(rawInputs, nameOrID)
found = true
break
}
}
if !found && !ignore {
return nil, nil, fmt.Errorf("unable to find container %q: %w", nameOrID, define.ErrNoSuchCtr)
}
}
return filtered, rawInputs, nil
}
func getPodsByContext(contextWithConnection context.Context, all bool, ignore bool, namesOrIDs []string) ([]*entities.ListPodsReport, error) {
if all && len(namesOrIDs) > 0 {
return nil, errors.New("cannot look up specific pods and all")
}
allPods, err := pods.List(contextWithConnection, nil)
if err != nil {
return nil, err
}
if all {
return allPods, nil
}
filtered := []*entities.ListPodsReport{}
// Note: it would be nicer if the lists endpoint would support that as
// we could use the libpod backend for looking up pods rather than
// risking diverging the local and remote lookups.
//
// A `--filter nameOrId=abc` that can be specified multiple times would
// be awesome to have.
for _, nameOrID := range namesOrIDs {
// First determine if the pod exists by doing an inspect.
// Inspect takes supports names and IDs and let's us determine
// a container's full ID.
inspectData, err := pods.Inspect(contextWithConnection, nameOrID, nil)
if err != nil {
if errorhandling.Contains(err, define.ErrNoSuchPod) {
if ignore {
continue
}
return nil, fmt.Errorf("unable to find pod %q: %w", nameOrID, define.ErrNoSuchPod)
}
return nil, err
}
// Now we can do a full match of the ID to find the right pod.
// Note that we *really* need a full ID match to prevent any
// ambiguities between IDs and names (see #7837).
found := false
for _, pod := range allPods {
if pod.Id == inspectData.ID {
filtered = append(filtered, pod)
found = true
break
}
}
if !found {
if ignore {
continue
}
return nil, fmt.Errorf("unable to find pod %q: %w", nameOrID, define.ErrNoSuchPod)
}
}
return filtered, nil
}