/
app_list.go
133 lines (119 loc) · 3.64 KB
/
app_list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"context"
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/theketchio/ketch/cmd/ketch/output"
ketchv1 "github.com/theketchio/ketch/internal/api/v1beta1"
"github.com/theketchio/ketch/internal/utils"
)
type appListOutput struct {
Name string `json:"name" yaml:"name"`
Framework string `json:"framework" yaml:"framework"`
State string `json:"state" yaml:"state"`
Addresses string `json:"addresses" yaml:"addresses"`
Builder string `json:"builder" yaml:"builder"`
Description string `json:"description" yaml:"description"`
}
const appListHelp = `
List all apps running on a kubernetes cluster.
`
func newAppListCmd(cfg config, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List all apps.",
Long: appListHelp,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return appList(cmd.Context(), cfg, out)
},
}
return cmd
}
func appList(ctx context.Context, cfg config, out io.Writer) error {
apps := ketchv1.AppList{}
if err := cfg.Client().List(ctx, &apps); err != nil {
return fmt.Errorf("failed to list apps: %w", err)
}
frameworks := ketchv1.FrameworkList{}
if err := cfg.Client().List(ctx, &frameworks); err != nil {
return fmt.Errorf("failed to list frameworks: %w", err)
}
frameworksByName := make(map[string]ketchv1.Framework, len(frameworks.Items))
for _, framework := range frameworks.Items {
frameworksByName[framework.Name] = framework
}
allPods, err := allAppsPods(ctx, cfg, apps.Items)
if err != nil {
return fmt.Errorf("failed to list apps pods: %w", err)
}
return output.Write(generateAppListOutput(apps, allPods, frameworksByName), out, "column")
}
func generateAppListOutput(apps ketchv1.AppList, allPods *corev1.PodList, frameworksByName map[string]ketchv1.Framework) []appListOutput {
var outputs []appListOutput
for _, item := range apps.Items {
pods := filterAppPods(item.Name, allPods.Items)
framework := frameworksByName[item.Spec.Framework]
urls := strings.Join(item.CNames(&framework), " ")
outputs = append(outputs, appListOutput{
Name: item.Name,
Framework: item.Spec.Framework,
State: appState(pods),
Addresses: urls,
Builder: item.Spec.Builder,
Description: item.Spec.Description,
})
}
return outputs
}
func allAppsPods(ctx context.Context, cfg config, apps []ketchv1.App) (*corev1.PodList, error) {
if len(apps) == 0 {
return &corev1.PodList{}, nil
}
selector := &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: utils.KetchAppNameLabel,
Operator: "Exists",
},
},
}
s, err := metav1.LabelSelectorAsSelector(selector)
if err != nil {
return nil, err
}
return cfg.KubernetesClient().CoreV1().Pods(metav1.NamespaceAll).List(ctx, metav1.ListOptions{
LabelSelector: s.String(),
})
}
func filterAppPods(appName string, pods []corev1.Pod) []corev1.Pod {
var appPods []corev1.Pod
for _, pod := range pods {
if pod.Labels[utils.KetchAppNameLabel] == appName {
appPods = append(appPods, pod)
}
}
return appPods
}
func appListNames(cfg config, nameFilter ...string) ([]string, error) {
apps := ketchv1.AppList{}
if err := cfg.Client().List(context.TODO(), &apps); err != nil {
return nil, fmt.Errorf("failed to list apps: %w", err)
}
appNames := make([]string, 0)
for _, a := range apps.Items {
if len(nameFilter) == 0 {
appNames = append(appNames, a.Name)
}
for _, filter := range nameFilter {
if strings.Contains(a.Name, filter) {
appNames = append(appNames, a.Name)
}
}
}
return appNames, nil
}