package containers import ( "context" "encoding/json" "fmt" "strings" "time" "github.com/containerd/containerd" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/cri/constants" "github.com/coroot/coroot-node-agent/common" "github.com/coroot/coroot-node-agent/proc" "github.com/coroot/logparser" "k8s.io/klog/v2" ) const containerdTimeout = 30 * time.Second var ( containerdClient *containerd.Client ) func ContainerdInit() error { sockets := []string{ "/var/snap/microk8s/common/run/containerd.sock", "/run/k0s/containerd.sock", "/run/k3s/containerd/containerd.sock", "/run/containerd/containerd.sock", } var err error for _, socket := range sockets { containerdClient, err = containerd.New(proc.HostPath(socket), containerd.WithDefaultNamespace(constants.K8sContainerdNamespace), containerd.WithTimeout(time.Second)) if err == nil { klog.Infoln("using", socket) break } } if containerdClient == nil { return fmt.Errorf( "couldn't connect to containerd through the following UNIX sockets [%s]: %s", strings.Join(sockets, ","), err, ) } return nil } func ContainerdInspect(containerID string) (*ContainerMetadata, error) { if containerdClient == nil { return nil, fmt.Errorf("containerd client not initialized") } ctx, cancel := context.WithTimeout(context.Background(), containerdTimeout) defer cancel() c, err := containerdClient.ContainerService().Get(ctx, containerID) if err != nil { return nil, err } res := &ContainerMetadata{ labels: c.Labels, image: c.Image, volumes: map[string]string{}, } var spec oci.Spec if err := json.Unmarshal(c.Spec.Value, &spec); err != nil { klog.Warningln(err) } else { for _, m := range spec.Mounts { res.volumes[m.Destination] = common.ParseKubernetesVolumeSource(m.Source) } } if data, ok := c.Extensions["io.cri-containerd.container.metadata"]; ok { var md = struct { // from data.TypeUrl Metadata struct { LogPath string } }{} if err := json.Unmarshal(data.Value, &md); err != nil { klog.Warningln(err) } else { res.logPath = md.Metadata.LogPath res.logDecoder = logparser.CriDecoder{} } } return res, nil }