14c1c70407
This uses the previously unusued lib/stats.go code to return data about container stats to the CRI API. Helpers have been built around filtering based on the OCI API, and CPU stat reporting has been fixed. No data on filesystem layer usage is returned at this time. Fixes one-half of #1248 Signed-off-by: Yann Ramin <atrus@stackworks.net>
133 lines
3.5 KiB
Go
133 lines
3.5 KiB
Go
package server
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/kubernetes-incubator/cri-o/oci"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/net/context"
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
|
)
|
|
|
|
// filterContainer returns whether passed container matches filtering criteria
|
|
func filterContainer(c *pb.Container, filter *pb.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(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
|
|
}
|
|
|
|
// ListContainers lists all containers by filters.
|
|
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)
|
|
}()
|
|
logrus.Debugf("ListContainersRequest %+v", req)
|
|
|
|
var ctrs []*pb.Container
|
|
filter := req.GetFilter()
|
|
ctrList, err := s.ContainerServer.ListContainers()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if filter != nil {
|
|
ctrList, err = s.filterContainerList(filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
for _, ctr := range ctrList {
|
|
podSandboxID := ctr.Sandbox()
|
|
cState := s.Runtime().ContainerStatus(ctr)
|
|
created := cState.Created.UnixNano()
|
|
rState := pb.ContainerState_CONTAINER_UNKNOWN
|
|
cID := ctr.ID()
|
|
img := &pb.ImageSpec{
|
|
Image: ctr.Image(),
|
|
}
|
|
c := &pb.Container{
|
|
Id: cID,
|
|
PodSandboxId: podSandboxID,
|
|
CreatedAt: created,
|
|
Labels: ctr.Labels(),
|
|
Metadata: ctr.Metadata(),
|
|
Annotations: ctr.Annotations(),
|
|
Image: img,
|
|
ImageRef: ctr.ImageRef(),
|
|
}
|
|
|
|
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
|
|
}
|
|
c.State = rState
|
|
|
|
// Filter by other criteria such as state and labels.
|
|
if filterContainer(c, req.Filter) {
|
|
ctrs = append(ctrs, c)
|
|
}
|
|
}
|
|
|
|
resp = &pb.ListContainersResponse{
|
|
Containers: ctrs,
|
|
}
|
|
logrus.Debugf("ListContainersResponse: %+v", resp)
|
|
return resp, nil
|
|
}
|