-
Notifications
You must be signed in to change notification settings - Fork 1k
/
container_list.go
94 lines (86 loc) · 2.61 KB
/
container_list.go
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
package server
import (
"context"
"strings"
"github.com/cri-o/cri-o/internal/log"
oci "github.com/cri-o/cri-o/internal/oci"
"k8s.io/apimachinery/pkg/fields"
types "k8s.io/cri-api/pkg/apis/runtime/v1"
)
// filterContainer returns whether passed container matches filtering criteria
func filterContainer(c *types.Container, filter *types.ContainerFilter) bool {
if filter != nil {
if filter.State != nil {
if c.State != filter.State.State {
return false
}
}
if filter.LabelSelector != nil {
sel := fields.SelectorFromSet(filter.LabelSelector)
if !sel.Matches(fields.Set(c.Labels)) {
return false
}
}
}
return true
}
// filterContainerList applies a protobuf-defined filter to retrieve only intended containers. Not matching
// the filter is not considered an error but will return an empty response.
func (s *Server) filterContainerList(ctx context.Context, filter *types.ContainerFilter, origCtrList []*oci.Container) []*oci.Container {
ctx, span := log.StartSpan(ctx)
defer span.End()
// Filter using container id and pod id first.
if filter.Id != "" {
c, err := s.ContainerServer.GetContainerFromShortID(ctx, filter.Id)
if err != nil {
// If we don't find a container ID with a filter, it should not
// be considered an error. Log a warning and return an empty struct
log.Warnf(ctx, "Unable to find container ID %s", filter.Id)
return nil
}
switch {
case filter.PodSandboxId == "":
return []*oci.Container{c}
case strings.HasPrefix(c.Sandbox(), filter.PodSandboxId):
return []*oci.Container{c}
default:
return nil
}
} else if filter.PodSandboxId != "" {
sb, err := s.getPodSandboxFromRequest(ctx, filter.PodSandboxId)
if err != nil {
return nil
}
return sb.Containers().List()
}
log.Debugf(ctx, "No filters were applied, returning full container list")
return origCtrList
}
// ListContainers lists all containers by filters.
func (s *Server) ListContainers(ctx context.Context, req *types.ListContainersRequest) (*types.ListContainersResponse, error) {
ctx, span := log.StartSpan(ctx)
defer span.End()
var ctrs []*types.Container
filter := req.Filter
ctrList, err := s.ContainerServer.ListContainers()
if err != nil {
return nil, err
}
if filter != nil {
ctrList = s.filterContainerList(ctx, filter, ctrList)
}
for _, ctr := range ctrList {
// Skip over containers that are still being created
if !ctr.Created() {
continue
}
c := ctr.CRIContainer()
// Filter by other criteria such as state and labels.
if filterContainer(c, req.Filter) {
ctrs = append(ctrs, c)
}
}
return &types.ListContainersResponse{
Containers: ctrs,
}, nil
}