145 lines
3.7 KiB
Go
145 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/client-go/kubernetes"
|
|
"log"
|
|
"slices"
|
|
"strconv"
|
|
)
|
|
|
|
type Cluster struct {
|
|
namespaces map[string]v1.Namespace
|
|
clientset *kubernetes.Clientset
|
|
// map of namespace to list of all pods
|
|
pods map[string][]v1.Pod
|
|
}
|
|
|
|
func NewCluster(clientset *kubernetes.Clientset) (*Cluster, error) {
|
|
cluster := &Cluster{
|
|
clientset: clientset,
|
|
namespaces: make(map[string]v1.Namespace),
|
|
pods: make(map[string][]v1.Pod),
|
|
}
|
|
nslist, err := cluster.clientset.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, ns := range nslist.Items {
|
|
cluster.namespaces[ns.Name] = ns
|
|
podList, err := cluster.clientset.CoreV1().Pods(ns.Name).List(context.Background(), metav1.ListOptions{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cluster.pods[ns.Name] = podList.Items
|
|
}
|
|
return cluster, nil
|
|
}
|
|
|
|
func (c *Cluster) Pods(application *Application) []v1.Pod {
|
|
selector, err := metav1.LabelSelectorAsSelector(application.Selector())
|
|
if err != nil {
|
|
log.Fatalf("Error creating selector: %v", err)
|
|
}
|
|
pods := c.pods[application.Namespace.Name]
|
|
pods = slices.DeleteFunc(slices.Clone(pods), func(pod v1.Pod) bool {
|
|
return !selector.Matches(labels.Set(pod.Labels))
|
|
})
|
|
return pods
|
|
}
|
|
|
|
func (c *Cluster) ServiceAccounts(application *Application) []string {
|
|
var res []string
|
|
for _, pod := range c.Pods(application) {
|
|
if !slices.Contains(res, pod.Spec.ServiceAccountName) {
|
|
res = append(res, pod.Spec.ServiceAccountName)
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (c *Cluster) OwnerReferences(application *Application) []string {
|
|
var ownerReferences []string
|
|
for _, pod := range c.Pods(application) {
|
|
//log.Printf(" %s %v", pod.Name, pod.OwnerReferences)
|
|
for _, ownerReference := range pod.OwnerReferences {
|
|
owner := ownerReference.Kind + "/" + ownerReference.Name
|
|
if !slices.Contains(ownerReferences, owner) {
|
|
ownerReferences = append(ownerReferences, owner)
|
|
}
|
|
}
|
|
}
|
|
return ownerReferences
|
|
}
|
|
|
|
func (c *Cluster) IsLinkerdEnabled(application *Application) bool {
|
|
pods := c.Pods(application)
|
|
|
|
ndisabled := 0
|
|
for _, pod := range pods {
|
|
if pod.Annotations["linkerd.io/inject"] == "enabled" {
|
|
return true
|
|
}
|
|
if pod.Annotations["linkerd.io/inject"] == "disabled" {
|
|
ndisabled++
|
|
}
|
|
}
|
|
if ndisabled == len(pods) {
|
|
return false
|
|
}
|
|
ns := c.namespaces[application.Namespace.Name]
|
|
return ns.Annotations["linkerd.io/inject"] == "enabled"
|
|
}
|
|
|
|
func (c *Cluster) NamespaceLIst() []v1.Namespace {
|
|
return MapValues(c.namespaces)
|
|
}
|
|
|
|
func (c *Cluster) Namespace(name string) v1.Namespace {
|
|
return c.namespaces[name]
|
|
}
|
|
|
|
func (c *Cluster) PodList(namespace string) []v1.Pod {
|
|
return c.pods[namespace]
|
|
}
|
|
|
|
func (c *Cluster) PortNumbers(application *Application) []Port {
|
|
if !c.IsLinkerdEnabled(application) {
|
|
return nil
|
|
}
|
|
tcpPorts := make(map[int]Port)
|
|
udpPorts := make(map[int]Port)
|
|
for _, pod := range c.Pods(application) {
|
|
for _, container := range pod.Spec.Containers {
|
|
if container.Name == "linkerd-proxy" {
|
|
continue
|
|
}
|
|
for _, port := range container.Ports {
|
|
switch port.Protocol {
|
|
case "TCP":
|
|
tcpPorts[int(port.ContainerPort)] = Port{
|
|
Port: strconv.Itoa(int(port.ContainerPort)),
|
|
Protocol: string(port.Protocol),
|
|
}
|
|
case "UDP":
|
|
udpPorts[int(port.ContainerPort)] = Port{
|
|
Port: strconv.Itoa(int(port.ContainerPort)),
|
|
Protocol: string(port.Protocol),
|
|
}
|
|
|
|
default:
|
|
panic(fmt.Sprintf("Unknown port type for pod %s/%s: %s",
|
|
pod.Namespace, pod.Name, port.Protocol))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
res := MapValues(tcpPorts)
|
|
res = append(res, MapValues(udpPorts)...)
|
|
return res
|
|
}
|