2016-11-22 16:49:54 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2017-11-09 10:10:35 +00:00
|
|
|
"time"
|
|
|
|
|
2016-11-22 16:49:54 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/oci"
|
2017-08-05 11:40:46 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2016-11-22 16:49:54 +00:00
|
|
|
"golang.org/x/net/context"
|
2017-02-23 02:32:42 +00:00
|
|
|
"k8s.io/apimachinery/pkg/fields"
|
2017-08-04 11:13:19 +00:00
|
|
|
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
2016-11-22 16:49:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// filterContainer returns whether passed container matches filtering criteria
|
|
|
|
func filterContainer(c *pb.Container, filter *pb.ContainerFilter) bool {
|
|
|
|
if filter != nil {
|
|
|
|
if filter.State != nil {
|
2017-02-03 14:41:28 +00:00
|
|
|
if c.State != filter.State.State {
|
2016-11-22 16:49:54 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if filter.LabelSelector != nil {
|
|
|
|
sel := fields.SelectorFromSet(filter.LabelSelector)
|
|
|
|
if !sel.Matches(fields.Set(c.Labels)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-01-07 22:16:46 +00:00
|
|
|
// 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(filter *pb.ContainerFilter) (ctrList []*oci.Container, err error) {
|
|
|
|
// Filter using container id and pod id first.
|
|
|
|
if filter.Id != "" {
|
|
|
|
id, err := s.CtrIDIndex().Get(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
|
|
|
|
logrus.Warn("unable to find container ID %s", filter.Id)
|
|
|
|
return []*oci.Container{}, nil
|
|
|
|
}
|
|
|
|
c := s.ContainerServer.GetContainer(id)
|
|
|
|
if c != nil {
|
|
|
|
if filter.PodSandboxId != "" {
|
|
|
|
if c.Sandbox() == filter.PodSandboxId {
|
|
|
|
ctrList = []*oci.Container{c}
|
|
|
|
} else {
|
|
|
|
ctrList = []*oci.Container{}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ctrList = []*oci.Container{c}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if filter.PodSandboxId != "" {
|
|
|
|
pod := s.ContainerServer.GetSandbox(filter.PodSandboxId)
|
|
|
|
if pod == nil {
|
|
|
|
ctrList = []*oci.Container{}
|
|
|
|
} else {
|
|
|
|
ctrList = pod.Containers().List()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-11-22 16:49:54 +00:00
|
|
|
// ListContainers lists all containers by filters.
|
2017-11-09 10:10:35 +00:00
|
|
|
func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersRequest) (resp *pb.ListContainersResponse, err error) {
|
|
|
|
const operation = "list_containers"
|
|
|
|
defer func() {
|
|
|
|
recordOperation(operation, time.Now())
|
|
|
|
recordError(operation, err)
|
|
|
|
}()
|
2016-11-22 16:49:54 +00:00
|
|
|
logrus.Debugf("ListContainersRequest %+v", req)
|
2017-11-09 10:10:35 +00:00
|
|
|
|
2016-11-22 16:49:54 +00:00
|
|
|
var ctrs []*pb.Container
|
2017-11-11 11:07:24 +00:00
|
|
|
filter := req.GetFilter()
|
2017-07-25 13:56:23 +00:00
|
|
|
ctrList, err := s.ContainerServer.ListContainers()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-11-22 16:49:54 +00:00
|
|
|
|
2017-11-11 11:07:24 +00:00
|
|
|
if filter != nil {
|
2018-01-07 22:16:46 +00:00
|
|
|
ctrList, err = s.filterContainerList(filter)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2016-11-22 16:49:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ctr := range ctrList {
|
|
|
|
podSandboxID := ctr.Sandbox()
|
2017-07-17 12:25:32 +00:00
|
|
|
cState := s.Runtime().ContainerStatus(ctr)
|
2016-11-22 16:49:54 +00:00
|
|
|
created := cState.Created.UnixNano()
|
|
|
|
rState := pb.ContainerState_CONTAINER_UNKNOWN
|
|
|
|
cID := ctr.ID()
|
2017-07-17 19:42:14 +00:00
|
|
|
img := &pb.ImageSpec{
|
|
|
|
Image: ctr.Image(),
|
|
|
|
}
|
2016-11-22 16:49:54 +00:00
|
|
|
c := &pb.Container{
|
2017-02-03 14:41:28 +00:00
|
|
|
Id: cID,
|
|
|
|
PodSandboxId: podSandboxID,
|
2017-03-27 17:14:11 +00:00
|
|
|
CreatedAt: created,
|
2016-11-22 16:49:54 +00:00
|
|
|
Labels: ctr.Labels(),
|
|
|
|
Metadata: ctr.Metadata(),
|
2016-12-12 10:12:03 +00:00
|
|
|
Annotations: ctr.Annotations(),
|
2017-07-17 19:42:14 +00:00
|
|
|
Image: img,
|
Return image references from the storage package
The image's canonical reference is a name with a digest of the image's
manifest, so in imageService.ImageStatus() and
imageService.ListImages(), divide the image's name list into tagged and
digested values, and if we have names, add canonical versions.
In Server.ContainerStatus(), return the image name as it was given to us
as the image, and the image digested reference as the image reference.
In Server.ListImages(), be sure to only return tagged names in the
RepoTags field. In Server.ImageStatus(), also return canonical
references in the RepoDigests field.
In Server.PullImage(), be sure that we consistently return the same
image reference for an image, whether we ended up pulling it or not.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-07-12 16:41:38 +00:00
|
|
|
ImageRef: ctr.ImageRef(),
|
2016-11-22 16:49:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch cState.Status {
|
|
|
|
case oci.ContainerStateCreated:
|
|
|
|
rState = pb.ContainerState_CONTAINER_CREATED
|
|
|
|
case oci.ContainerStateRunning:
|
|
|
|
rState = pb.ContainerState_CONTAINER_RUNNING
|
|
|
|
case oci.ContainerStateStopped:
|
|
|
|
rState = pb.ContainerState_CONTAINER_EXITED
|
|
|
|
}
|
2017-02-03 14:41:28 +00:00
|
|
|
c.State = rState
|
2016-11-22 16:49:54 +00:00
|
|
|
|
|
|
|
// Filter by other criteria such as state and labels.
|
|
|
|
if filterContainer(c, req.Filter) {
|
|
|
|
ctrs = append(ctrs, c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-09 10:10:35 +00:00
|
|
|
resp = &pb.ListContainersResponse{
|
2016-11-22 16:49:54 +00:00
|
|
|
Containers: ctrs,
|
|
|
|
}
|
|
|
|
logrus.Debugf("ListContainersResponse: %+v", resp)
|
|
|
|
return resp, nil
|
|
|
|
}
|