pkg/process/finders/kubernetes/container.go (111 lines of code) (raw):

// Licensed to Apache Software Foundation (ASF) under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Apache Software Foundation (ASF) licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package kubernetes import ( "context" "strings" "k8s.io/client-go/kubernetes/scheme" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/rest" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type PodContainer struct { // pod references Pod *v1.Pod ContainerSpec v1.Container ContainerStatus v1.ContainerStatus // the kubernetes resource registry registry Registry } // AnalyzeContainers means query the containers by pod func AnalyzeContainers(pod *v1.Pod, registry Registry) []*PodContainer { containers := make([]*PodContainer, 0) // nolint for _, cs := range pod.Status.ContainerStatuses { // nolint for _, c := range pod.Spec.Containers { if c.Name != cs.Name { continue } containers = append(containers, &PodContainer{ Pod: pod, ContainerSpec: c, ContainerStatus: cs, registry: registry, }) } } return containers } func (c *PodContainer) CGroupID() string { cgroupID := c.ContainerStatus.ContainerID // delete the container runtime prefix is the cgroupid cgroupID = strings.TrimPrefix(cgroupID, "containerd://") cgroupID = strings.TrimPrefix(cgroupID, "dockerd://") cgroupID = strings.TrimPrefix(cgroupID, "docker://") cgroupID = strings.TrimPrefix(cgroupID, "cri-o://") return cgroupID } func (c *PodContainer) ServiceName() string { return c.registry.FindServiceName(c.Pod.Namespace, c.Pod.Name) } // FindOwner means query the owner in the container, it would loop up with parent owner until empty func (c *PodContainer) FindOwner(ctx context.Context, kindName string, k8sConfig *rest.Config) (*metav1.OwnerReference, error) { // find in cache result findedReferences := make([]metav1.OwnerReference, 0) if owner := c.findOwner(c.Pod.OwnerReferences, kindName); owner != nil { return owner, nil } findedReferences = append(findedReferences, c.Pod.OwnerReferences...) // found from owner for len(findedReferences) > 0 { current := findedReferences[0] findedReferences = findedReferences[1:] // must be a controller if c := current.Controller; c != nil && !*c { continue } // query reference data restClient, err := c.parseRestClientFromAPIVersion(k8sConfig, current.APIVersion) if err != nil { return nil, err } do := restClient.Get().Resource(current.Kind + "s"). Name(current.Name). Namespace(c.Pod.Namespace). Do(ctx) if do.Error() != nil { return nil, do.Error() } data := &unstructured.Unstructured{} if err := do.Into(data); err != nil { return nil, err } // query parent references from current reference references := data.GetOwnerReferences() if owner := c.findOwner(references, kindName); owner != nil { return owner, nil } findedReferences = append(findedReferences, references...) } return nil, nil } func (c *PodContainer) FindContainerFromSamePod(name string) *PodContainer { cs := AnalyzeContainers(c.Pod, c.registry) for _, co := range cs { if co.ContainerSpec.Name == name { return co } } return nil } func (c *PodContainer) parseRestClientFromAPIVersion(conf *rest.Config, apiVersion string) (rest.Interface, error) { groupVersion, err := schema.ParseGroupVersion(apiVersion) if err != nil { return nil, err } queryConf := rest.CopyConfig(conf) queryConf.GroupVersion = &groupVersion queryConf.APIPath = "/apis" queryConf.NegotiatedSerializer = scheme.Codecs.WithoutConversion() if queryConf.UserAgent == "" { queryConf.UserAgent = rest.DefaultKubernetesUserAgent() } return rest.RESTClientFor(queryConf) } func (c *PodContainer) findOwner(refs []metav1.OwnerReference, kindName string) *metav1.OwnerReference { for _, o := range refs { if o.Kind == kindName { return &o } } return nil }