pkg/kt/command/birdseye/common.go
package birdseye
import (
"fmt"
opt "github.com/alibaba/kt-connect/pkg/kt/command/options"
"github.com/alibaba/kt-connect/pkg/kt/service/cluster"
"github.com/alibaba/kt-connect/pkg/kt/util"
appV1 "k8s.io/api/apps/v1"
coreV1 "k8s.io/api/core/v1"
"strings"
)
const UnknownUser = "unknown user"
func GetKtPodsAndAllServices(namespace string) ([]coreV1.Pod, []coreV1.Service, []coreV1.Service, error) {
pods, err := cluster.Ins().GetPodsByLabel(map[string]string{util.ControlBy: util.KubernetesToolkit}, namespace)
if err != nil {
return nil, nil, nil, err
}
svcs, err := cluster.Ins().GetAllServiceInNamespace(opt.Get().Global.Namespace)
if err != nil {
return nil, nil, nil, err
}
ktSvcs := make([]coreV1.Service, 0)
otherSvcs := make([]coreV1.Service, 0)
for _, svc := range svcs.Items {
if svc.Labels[util.ControlBy] == util.KubernetesToolkit {
ktSvcs = append(ktSvcs, svc)
} else {
otherSvcs = append(otherSvcs, svc)
}
}
return pods.Items, ktSvcs, otherSvcs, nil
}
func GetKtPodsAndDeployments() ([]coreV1.Pod, []appV1.Deployment, error) {
ktConnectLabel := map[string]string{util.ControlBy: util.KubernetesToolkit, util.KtRole: util.RoleConnectShadow}
pods, err := cluster.Ins().GetPodsByLabel(ktConnectLabel, "")
if err != nil {
return nil, nil, err
}
apps, err := cluster.Ins().GetDeploymentsByLabel(ktConnectLabel, "")
if err != nil {
return nil, nil, err
}
return pods.Items, apps.Items, nil
}
func GetConnectors(pods []coreV1.Pod, apps []appV1.Deployment) []string {
users:= make([]string, 0)
for _, pod := range pods {
if user := checkConnector(pod.Annotations); user != "" {
users = append(users, user)
}
}
for _, app := range apps {
if user := checkConnector(app.Annotations); user != "" {
users = append(users, user)
}
}
return users
}
func GetServiceStatus(ktSvcs []coreV1.Service, pods []coreV1.Pod, svcs []coreV1.Service) [][]string {
allServices := make([][]string, 0)
for _, svc := range ktSvcs {
for _, p := range pods {
if p.Labels[util.KtRole] == util.RolePreviewShadow && util.MapContains(svc.Spec.Selector, p.Labels) {
allServices = append(allServices, []string{svc.Name, fmt.Sprintf("previewing by [%s]", getUserName(p))})
break
}
}
}
svcLoop:
for _, svc := range svcs {
for _, p := range pods {
if util.MapContains(svc.Spec.Selector, p.Labels) {
if role := p.Labels[util.KtRole]; role == util.RoleExchangeShadow {
allServices = append(allServices, []string{svc.Name, fmt.Sprintf("exchanged by [%s]", getUserName(p))})
continue svcLoop
} else if role == util.RoleRouter {
allServices = append(allServices, []string{svc.Name, "meshed (auto) by " +
getMeshedUserNames(ktSvcs, pods, svc.Name + util.MeshPodInfix)})
continue svcLoop
} else if role == util.RoleMeshShadow {
allServices = append(allServices, []string{svc.Name, "meshed (manual) by " +
getMeshedUserNames([]coreV1.Service{svc}, pods, svc.Name)})
continue svcLoop
}
}
}
if !opt.Get().Birdseye.HideNaturalService {
allServices = append(allServices, []string{svc.Name, "normal"})
}
}
return allServices
}
func getUserName(p coreV1.Pod) string {
user := p.Annotations[util.KtUser]
if user == "" {
user = UnknownUser
}
return user
}
func getMeshedUserNames(svcs []coreV1.Service, pods []coreV1.Pod, namePrefix string) string {
users := make([]string, 0)
for _, s := range svcs {
if strings.HasPrefix(s.Name, namePrefix) {
for _, p := range pods {
if p.Labels[util.KtRole] == util.RoleMeshShadow && util.MapContains(s.Spec.Selector, p.Labels) {
user := p.Annotations[util.KtUser]
if user != "" {
users = append(users, user)
}
break
}
}
}
}
if len(users) == 0 {
return UnknownUser
}
return "[" + strings.Join(users, "], [") + "]"
}
func checkConnector(annotations map[string]string) string {
if user, exists := annotations[util.KtUser]; exists {
lastHeartBeat := util.ParseTimestamp(annotations[util.KtLastHeartBeat])
if lastHeartBeat > 0 {
lastActiveInMin := (util.GetTime() - lastHeartBeat) / 60
return fmt.Sprintf("%s (last active %d min ago)", user, lastActiveInMin)
} else {
return user
}
} else {
return UnknownUser
}
}