package resource // BOZO!! // import ( // "context" // "errors" // "fmt" // "strconv" // "strings" // "github.com/derailed/k9s/internal/k8s" // v1 "k8s.io/api/core/v1" // mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1" // ) // type ( // // Container represents a container on a pod. // Container struct { // *Base // pod *v1.Pod // instance v1.Container // metrics *mv1beta1.PodMetrics // } // ) // // NewContainerList returns a collection of container. // func NewContainerList(c Connection, pod *v1.Pod) List { // return NewList( // NotNamespaced, // "containers", // NewContainer(c, pod), // 0, // ) // } // // NewContainer returns a new set of containers. // func NewContainer(c Connection, pod *v1.Pod) *Container { // co := Container{ // Base: &Base{Connection: c, Resource: k8s.NewPod(c)}, // pod: pod, // } // co.Factory = &co // return &co // } // // New builds a new Container instance from a k8s resource. // func (r *Container) New(i interface{}) (Columnar, error) { // co := NewContainer(r.Connection, r.pod) // coi, ok := i.(v1.Container) // if !ok { // return nil, errors.New("Expecting a container resource") // } // co.instance = coi // co.path = r.namespacedName(r.pod.ObjectMeta) + ":" + co.instance.Name // return co, nil // } // // SetPodMetrics set the current k8s resource metrics on associated pod. // func (r *Container) SetPodMetrics(m *mv1beta1.PodMetrics) { // r.metrics = m // } // // Marshal resource to yaml. // func (r *Container) Marshal(path string) (string, error) { // return "", nil // } // // Logs tails a given container logs // func (r *Container) Logs(ctx context.Context, c chan<- string, opts LogOptions) error { // res, ok := r.Resource.(k8s.Loggable) // if !ok { // return fmt.Errorf("Resource %T is not Loggable", r.Resource) // } // return tailLogs(ctx, res, c, opts) // } // // List resources for a given namespace. // func (r *Container) List(ctx context.Context, ns string) (Columnars, error) { // icos := r.pod.Spec.InitContainers // cos := r.pod.Spec.Containers // cc := make(Columnars, 0, len(icos)+len(cos)) // for _, co := range icos { // res, err := r.New(co) // if err != nil { // return nil, err // } // cc = append(cc, res) // } // for _, co := range cos { // res, err := r.New(co) // if err != nil { // return nil, err // } // cc = append(cc, res) // } // return cc, nil // } // // Header return resource header. // func (*Container) Header(ns string) Row { // return append(Row{}, // "NAME", // "IMAGE", // "READY", // "STATE", // "RS", // "PROBES(L:R)", // "CPU", // "MEM", // "%CPU", // "%MEM", // "PORTS", // "AGE", // ) // } // // NumCols designates if column is numerical. // func (*Container) NumCols(n string) map[string]bool { // return map[string]bool{ // "CPU": true, // "MEM": true, // "%CPU": true, // "%MEM": true, // "RS": true, // } // } // // Fields retrieves displayable fields. // func (r *Container) Fields(ns string) Row { // ff := make(Row, 0, len(r.Header(ns))) // i := r.instance // c, p := gatherMetrics(i, r.metrics) // ready, state, restarts := "false", MissingValue, "0" // cs := getContainerStatus(i.Name, r.pod.Status) // if cs != nil { // ready, state, restarts = boolToStr(cs.Ready), toState(cs.State), strconv.Itoa(int(cs.RestartCount)) // } // return append(ff, // i.Name, // i.Image, // ready, // state, // restarts, // probe(i.LivenessProbe)+":"+probe(i.ReadinessProbe), // c.cpu, // c.mem, // p.cpu, // p.mem, // toStrPorts(i.Ports), // toAge(r.pod.CreationTimestamp), // ) // } // // ---------------------------------------------------------------------------- // // Helpers... // func gatherMetrics(co v1.Container, mx *mv1beta1.PodMetrics) (c, p metric) { // c, p = noMetric(), noMetric() // if mx == nil { // return // } // var ( // cpu int64 // mem float64 // ) // for _, c := range mx.Containers { // if c.Name == co.Name { // cpu = c.Usage.Cpu().MilliValue() // mem = k8s.ToMB(c.Usage.Memory().Value()) // break // } // } // c = metric{ // cpu: ToMillicore(cpu), // mem: ToMi(mem), // } // rcpu, rmem := containerResources(co) // if rcpu != nil { // p.cpu = AsPerc(toPerc(float64(cpu), float64(rcpu.MilliValue()))) // } // if rmem != nil { // p.mem = AsPerc(toPerc(mem, k8s.ToMB(rmem.Value()))) // } // return // } // func getContainerStatus(co string, status v1.PodStatus) *v1.ContainerStatus { // for _, c := range status.ContainerStatuses { // if c.Name == co { // return &c // } // } // for _, c := range status.InitContainerStatuses { // if c.Name == co { // return &c // } // } // return nil // } // func toStrPorts(pp []v1.ContainerPort) string { // ports := make([]string, len(pp)) // for i, p := range pp { // if len(p.Name) > 0 { // ports[i] = p.Name + ":" // } // ports[i] += strconv.Itoa(int(p.ContainerPort)) // if p.Protocol != "TCP" { // ports[i] += "╱" + string(p.Protocol) // } // } // return strings.Join(ports, ",") // } // func toState(s v1.ContainerState) string { // switch { // case s.Waiting != nil: // if s.Waiting.Reason != "" { // return s.Waiting.Reason // } // return "Waiting" // case s.Terminated != nil: // if s.Terminated.Reason != "" { // return s.Terminated.Reason // } // return Terminating // case s.Running != nil: // return Running // default: // return MissingValue // } // } // func toRes(r v1.ResourceList) (string, string) { // cpu, mem := r[v1.ResourceCPU], r[v1.ResourceMemory] // return ToMillicore(cpu.MilliValue()), ToMi(k8s.ToMB(mem.Value())) // } // func probe(p *v1.Probe) string { // if p == nil { // return "off" // } // return "on" // } // func asMi(v int64) float64 { // return float64(v) / 1024 * 1024 // }