aboutsummaryrefslogtreecommitdiff
path: root/pkg/domain/infra/tunnel/helpers.go
blob: 90d55811953f5f753fe2e76a6e05a9bcd0d64f65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package tunnel

import (
	"context"
	"errors"
	"fmt"

	"github.com/containers/podman/v4/libpod/define"
	"github.com/containers/podman/v4/pkg/bindings/containers"
	"github.com/containers/podman/v4/pkg/bindings/pods"
	"github.com/containers/podman/v4/pkg/domain/entities"
	"github.com/containers/podman/v4/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")
	}
	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{}
	switch {
	case len(filters) > 0:
		namesOrIDs = nil
		for i := range allContainers {
			if len(namesOrIDs) > 0 {
				for _, name := range namesOrIDs {
					if name == allContainers[i].ID {
						namesOrIDs = append(namesOrIDs, allContainers[i].ID)
					}
				}
			} else {
				namesOrIDs = append(namesOrIDs, allContainers[i].ID)
			}
		}
	case all:
		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 that 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 containers 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, 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 containers full ID.
		inspectData, err := pods.Inspect(contextWithConnection, nameOrID, nil)
		if err != nil {
			if errorhandling.Contains(err, define.ErrNoSuchPod) {
				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 {
			return nil, fmt.Errorf("unable to find pod %q: %w", nameOrID, define.ErrNoSuchPod)
		}
	}
	return filtered, nil
}