github.com/oam-dev/kubevela@v1.9.11/references/cli/top/model/container.go (about)

     1  /*
     2  Copyright 2022 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package model
    18  
    19  import (
    20  	"context"
    21  	"strconv"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/types"
    25  	"k8s.io/client-go/rest"
    26  	"sigs.k8s.io/controller-runtime/pkg/client"
    27  
    28  	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    29  	"github.com/oam-dev/kubevela/pkg/multicluster"
    30  	clicommon "github.com/oam-dev/kubevela/references/common"
    31  )
    32  
    33  // Container represent the container resource instance
    34  type Container struct {
    35  	name               string
    36  	image              string
    37  	ready              string
    38  	state              string
    39  	CPU                string
    40  	Mem                string
    41  	CPUR               string
    42  	CPUL               string
    43  	MemR               string
    44  	MemL               string
    45  	lastTerminationMsg string
    46  	restartCount       string
    47  }
    48  
    49  // ContainerList is container list
    50  type ContainerList []Container
    51  
    52  // ListContainerOfPod get the container data of aimed pod
    53  func ListContainerOfPod(ctx context.Context, client client.Client, cfg *rest.Config) (ContainerList, error) {
    54  	name := ctx.Value(&CtxKeyPod).(string)
    55  	namespace := ctx.Value(&CtxKeyNamespace).(string)
    56  	cluster := ctx.Value(&CtxKeyCluster).(string)
    57  
    58  	pod := v1.Pod{}
    59  	err := client.Get(multicluster.ContextWithClusterName(context.Background(), cluster), types.NamespacedName{Name: name, Namespace: namespace}, &pod)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	usageMap := fetchContainerMetricsUsageMap(cfg, name, namespace, cluster)
    65  	lrMap := fetchContainerMetricsLRMap(pod.Spec)
    66  
    67  	containers := make([]Container, 0)
    68  	for _, c := range pod.Status.ContainerStatuses {
    69  		containers = append(containers, loadContainerDetail(c, usageMap, lrMap))
    70  	}
    71  	return containers, nil
    72  }
    73  
    74  func loadContainerDetail(c v1.ContainerStatus, usageMap map[string]v1.ResourceList, lrMap map[string]v1.ResourceRequirements) Container {
    75  	containerInfo := Container{
    76  		name:               c.Name,
    77  		image:              c.Image,
    78  		CPU:                clicommon.MetricsNA,
    79  		Mem:                clicommon.MetricsNA,
    80  		CPUR:               clicommon.MetricsNA,
    81  		CPUL:               clicommon.MetricsNA,
    82  		MemR:               clicommon.MetricsNA,
    83  		MemL:               clicommon.MetricsNA,
    84  		lastTerminationMsg: "",
    85  		restartCount:       string(c.RestartCount),
    86  	}
    87  	if c.Ready {
    88  		containerInfo.ready = "Yes"
    89  	} else {
    90  		containerInfo.ready = "No"
    91  	}
    92  	containerInfo.state = common.ContainerStateToString(c.State)
    93  
    94  	usage, ok1 := usageMap[c.Name]
    95  	lr, ok2 := lrMap[c.Name]
    96  	if ok1 && ok2 {
    97  		cpuUsage := usage.Cpu().MilliValue()
    98  		memUsage := usage.Memory().Value()
    99  		containerInfo.CPU, containerInfo.Mem = strconv.FormatInt(cpuUsage, 10), strconv.FormatInt(memUsage/1000000, 10)
   100  		containerInfo.CPUR = clicommon.ToPercentageStr(cpuUsage, lr.Requests.Cpu().MilliValue())
   101  		containerInfo.CPUL = clicommon.ToPercentageStr(cpuUsage, lr.Limits.Cpu().MilliValue())
   102  		containerInfo.MemR = clicommon.ToPercentageStr(memUsage, lr.Requests.Memory().Value())
   103  		containerInfo.MemL = clicommon.ToPercentageStr(memUsage, lr.Limits.Memory().Value())
   104  	}
   105  	if c.LastTerminationState.Terminated != nil {
   106  		containerInfo.lastTerminationMsg = c.LastTerminationState.Terminated.Message
   107  	}
   108  	return containerInfo
   109  }
   110  
   111  func fetchContainerMetricsUsageMap(cfg *rest.Config, name, namespace, cluster string) map[string]v1.ResourceList {
   112  	metric, err := clicommon.GetPodMetrics(cfg, name, namespace, cluster)
   113  	if err != nil {
   114  		return nil
   115  	}
   116  	cmx := make(map[string]v1.ResourceList, len(metric.Containers))
   117  	for i := range metric.Containers {
   118  		c := metric.Containers[i]
   119  		cmx[c.Name] = c.Usage
   120  	}
   121  	return cmx
   122  }
   123  
   124  func fetchContainerMetricsLRMap(spec v1.PodSpec) map[string]v1.ResourceRequirements {
   125  	lr := make(map[string]v1.ResourceRequirements, len(spec.Containers))
   126  	for _, container := range spec.Containers {
   127  		lr[container.Name] = container.Resources
   128  	}
   129  	return lr
   130  }
   131  
   132  // ToTableBody generate body of table in pod view
   133  func (l ContainerList) ToTableBody() [][]string {
   134  	data := make([][]string, len(l))
   135  	for index, container := range l {
   136  		data[index] = []string{container.name, container.image, container.ready, container.state, container.CPU, container.Mem, container.CPUR, container.CPUL, container.MemR, container.MemL, container.lastTerminationMsg, container.restartCount}
   137  	}
   138  	return data
   139  }