plugin/commander/container/util/cri/list.go (82 lines of code) (raw):
package cri
import (
"sort"
"strings"
"time"
criapis "k8s.io/cri-api/pkg/apis"
runtimeapis "k8s.io/cri-api/pkg/apis/runtime/v1"
"k8s.io/kubernetes/pkg/kubelet/cri/remote"
"github.com/aliyun/aliyun_assist_client/agent/log"
"github.com/aliyun/aliyun_assist_client/plugin/commander/container/util/model"
)
func ListContainers(connectTimeout time.Duration, showAllContainers bool) ([]model.Container, error) {
containerFilter := &runtimeapis.ContainerFilter{}
if !showAllContainers {
containerFilter.State = &runtimeapis.ContainerStateValue{
State: runtimeapis.ContainerState_CONTAINER_RUNNING,
}
}
containers := []model.Container{}
// Since both old dockershim inside kubelet and new standalone cri-docker
// provide CRI to docker, runtime endpoints need to be deduplicated based on
// runtime name.
uniqueRuntimeNames := make([]string, len(RuntimeName2Endpoints))
for uniqueRuntimeName := range RuntimeName2Endpoints {
uniqueRuntimeNames = append(uniqueRuntimeNames, uniqueRuntimeName)
}
sort.Strings(uniqueRuntimeNames)
for _, sortedRuntimeName := range uniqueRuntimeNames {
for _, endpoint := range RuntimeName2Endpoints[sortedRuntimeName] {
service, err := remote.NewRemoteRuntimeService(endpoint.Endpoint, connectTimeout)
if err != nil {
log.GetLogger().WithError(err).Errorf("Failed to connect %s runtime via %s", endpoint.RuntimeName, endpoint.Endpoint)
continue
}
oneRuntimeContainers, err := listCRIContainers(service, endpoint.RuntimeName, containerFilter)
if err != nil {
log.GetLogger().WithError(err).Errorf("Failed to list containers on %s runtime via %s", endpoint.RuntimeName, endpoint.Endpoint)
continue
}
// Sort containers on one runtime by container id lexicographically
sort.SliceStable(oneRuntimeContainers, func(i, j int) bool {
return oneRuntimeContainers[i].Id < oneRuntimeContainers[j].Id
})
containers = append(containers, oneRuntimeContainers...)
// Only one available runtime endpoint is needed for the container
// runtime
break
}
}
return containers, nil
}
func listCRIContainers(service criapis.RuntimeService, runtimeName string, containerFilter *runtimeapis.ContainerFilter) ([]model.Container, error) {
criPodSandboxes, err := service.ListPodSandbox(&runtimeapis.PodSandboxFilter{})
if err != nil {
return nil, err
}
podSandboxId2Names := make(map[string]string, len(criPodSandboxes))
for _, podSandbox := range criPodSandboxes {
if podSandbox.Metadata != nil && podSandbox.Metadata.Name != "" {
podSandboxId2Names[podSandbox.Id] = podSandbox.Metadata.Name
}
}
criContainers, err := service.ListContainers(containerFilter)
if err != nil {
return nil, err
}
var containers []model.Container
for _, criContainer := range criContainers {
container := model.Container{
Id: criContainer.Id,
PodId: criContainer.PodSandboxId,
RuntimeName: runtimeName,
State: containerState2String(criContainer.State),
DataSource: model.ViaCRI,
}
if criContainer.Metadata != nil {
container.Name = criContainer.Metadata.Name
}
if podSandboxName, ok := podSandboxId2Names[container.PodId]; ok {
container.PodName = podSandboxName
}
containers = append(containers, container)
}
return containers, nil
}
func containerState2String(state runtimeapis.ContainerState) string {
return strings.TrimPrefix(state.String(), "CONTAINER_")
}