@@ -3,7 +3,6 @@ package internal
3
3
import (
4
4
"context"
5
5
"flag"
6
- "fmt"
7
6
tea "github.com/charmbracelet/bubbletea/v2"
8
7
"github.com/charmbracelet/lipgloss/v2"
9
8
"github.com/robinovitch61/kl/internal/command"
@@ -13,13 +12,8 @@ import (
13
12
"github.com/robinovitch61/kl/internal/model"
14
13
"github.com/robinovitch61/kl/internal/page"
15
14
"github.com/robinovitch61/kl/internal/style"
16
- "k8s.io/client-go/kubernetes"
17
15
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc" // register OIDC auth provider
18
- "k8s.io/client-go/tools/clientcmd"
19
- "k8s.io/client-go/tools/clientcmd/api"
20
16
"k8s.io/klog/v2"
21
- "os"
22
- "strings"
23
17
"time"
24
18
)
25
19
@@ -40,152 +34,29 @@ func initializedModel(m Model) (Model, tea.Cmd, error) {
40
34
// - specifying multiple contexts that point to the same cluster
41
35
// - I can't imagine a scenario where this is desired other than wanting multiple namespaces per cluster
42
36
43
- m , err := initializeKubeConfig (m )
37
+ ctx , cancel := context .WithCancel (context .Background ())
38
+ m .cancel = cancel
39
+ c , err := client .NewClient (
40
+ ctx ,
41
+ m .config .KubeConfigPath ,
42
+ m .config .Contexts ,
43
+ m .config .Namespaces ,
44
+ m .config .AllNamespaces ,
45
+ )
44
46
if err != nil {
45
47
return m , nil , err
46
48
}
49
+ m .client = c
47
50
48
- m = initializePages (m )
49
-
50
- cmds := createInitialCommands (m )
51
-
52
- return m , tea .Batch (cmds ... ), nil
53
- }
54
-
55
- // TODO LEO: make this part of client initialization
56
- func initializeKubeConfig (m Model ) (Model , error ) {
57
- rawKubeConfig , loadingRules , err := getKubeConfig (m .config .KubeConfigPath )
58
- if err != nil {
59
- return m , err
60
- }
61
-
62
- contexts , err := getContexts (m .config .Contexts , rawKubeConfig )
63
- if err != nil {
64
- return m , err
65
- }
66
- dev .Debug (fmt .Sprintf ("using contexts %v" , contexts ))
67
-
68
- clusters := getClustersFromContexts (contexts , rawKubeConfig )
69
-
70
- clusterToContext , err := validateUniqueClusters (contexts , clusters , rawKubeConfig )
71
- if err != nil {
72
- return m , err
73
- }
74
-
75
- allClusterNamespaces := buildClusterNamespaces (m , clusters , clusterToContext , rawKubeConfig )
76
- m .allClusterNamespaces = allClusterNamespaces
77
- logClusterNamespaces (allClusterNamespaces )
78
-
79
- clusterToClientSet , err := createClientSets (clusters , clusterToContext , loadingRules )
80
- if err != nil {
81
- return m , err
82
- }
83
-
84
- ctx , cancel := context .WithCancel (context .Background ())
85
- m .cancel = cancel
86
- m .client = client .NewClient (ctx , clusterToClientSet )
87
- m .entityTree = model .NewEntityTree (m .allClusterNamespaces )
51
+ m .entityTree = model .NewEntityTree (m .client .AllClusterNamespaces ())
88
52
89
53
m .termStyleData = style .NewTermStyleData ()
90
54
91
- return m , nil
92
- }
93
-
94
- func getClustersFromContexts (contexts []string , rawKubeConfig api.Config ) []string {
95
- var clusters []string
96
- for _ , contextName := range contexts {
97
- clusterName := rawKubeConfig .Contexts [contextName ].Cluster
98
- clusters = append (clusters , clusterName )
99
- }
100
- return clusters
101
- }
102
-
103
- func validateUniqueClusters (contexts []string , clusters []string , rawKubeConfig api.Config ) (map [string ]string , error ) {
104
- clusterToContext := make (map [string ]string )
105
- for _ , contextName := range contexts {
106
- clusterName := rawKubeConfig .Contexts [contextName ].Cluster
107
- if existingContext , exists := clusterToContext [clusterName ]; exists {
108
- return nil , fmt .Errorf ("contexts %s and %s both specify cluster %s - unclear which auth/namespace to use" , existingContext , contextName , clusterName )
109
- }
110
- clusterToContext [clusterName ] = contextName
111
- }
112
- return clusterToContext , nil
113
- }
114
-
115
- func buildClusterNamespaces (m Model , clusters []string , clusterToContext map [string ]string , rawKubeConfig api.Config ) []model.ClusterNamespaces {
116
- namespacesString := strings .Trim (strings .TrimSpace (m .config .Namespaces ), "," )
117
- var namespaces []string
118
- if len (namespacesString ) > 0 {
119
- namespaces = strings .Split (namespacesString , "," )
120
- }
121
-
122
- var allClusterNamespaces []model.ClusterNamespaces
123
- for _ , cluster := range clusters {
124
- if m .config .AllNamespaces {
125
- cn := model.ClusterNamespaces {Cluster : cluster , Namespaces : []string {"" }}
126
- allClusterNamespaces = append (allClusterNamespaces , cn )
127
- } else if len (namespaces ) > 0 {
128
- cn := model.ClusterNamespaces {Cluster : cluster , Namespaces : namespaces }
129
- allClusterNamespaces = append (allClusterNamespaces , cn )
130
- } else {
131
- contextName := clusterToContext [cluster ]
132
- namespace := rawKubeConfig .Contexts [contextName ].Namespace
133
- if namespace == "" {
134
- namespace = "default"
135
- }
136
- cn := model.ClusterNamespaces {Cluster : cluster , Namespaces : []string {namespace }}
137
- allClusterNamespaces = append (allClusterNamespaces , cn )
138
- }
139
- }
140
- return allClusterNamespaces
141
- }
142
-
143
- func logClusterNamespaces (allClusterNamespaces []model.ClusterNamespaces ) {
144
- for _ , cn := range allClusterNamespaces {
145
- for _ , namespace := range cn .Namespaces {
146
- dev .Debug (fmt .Sprintf ("using cluster '%s' namespace '%s'" , cn .Cluster , namespace ))
147
- }
148
- }
149
- }
150
-
151
- func createClientSets (clusters []string , clusterToContext map [string ]string , loadingRules * clientcmd.ClientConfigLoadingRules ) (map [string ]* kubernetes.Clientset , error ) {
152
- clusterToClientSet := make (map [string ]* kubernetes.Clientset )
153
- for _ , cluster := range clusters {
154
- clientset , err := createClientSetForCluster (cluster , clusterToContext , loadingRules )
155
- if err != nil {
156
- return nil , err
157
- }
158
- clusterToClientSet [cluster ] = clientset
159
- }
160
- return clusterToClientSet , nil
161
- }
162
-
163
- func createClientSetForCluster (cluster string , clusterToContext map [string ]string , loadingRules * clientcmd.ClientConfigLoadingRules ) (* kubernetes.Clientset , error ) {
164
- contextName , exists := clusterToContext [cluster ]
165
- if ! exists {
166
- return nil , fmt .Errorf ("no context found for cluster %s in kubeconfig" , cluster )
167
- }
168
-
169
- // create a config override that sets the current context
170
- overrides := & clientcmd.ConfigOverrides {
171
- CurrentContext : contextName ,
172
- }
173
-
174
- dev .Debug (fmt .Sprintf ("using context %s for cluster %s" , contextName , cluster ))
175
-
176
- // create client config with the override
177
- clientConfig := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (loadingRules , overrides )
178
- config , err := clientConfig .ClientConfig ()
179
- if err != nil {
180
- return nil , fmt .Errorf ("failed to get client config for cluster %s: %w" , cluster , err )
181
- }
55
+ m = initializePages (m )
182
56
183
- clientset , err := kubernetes .NewForConfig (config )
184
- if err != nil {
185
- return nil , fmt .Errorf ("failed to create clientset for cluster %s: %w" , cluster , err )
186
- }
57
+ cmds := createInitialCommands (m )
187
58
188
- return clientset , nil
59
+ return m , tea . Batch ( cmds ... ) , nil
189
60
}
190
61
191
62
func initializePages (m Model ) Model {
@@ -216,7 +87,7 @@ func initializePages(m Model) Model {
216
87
217
88
func createInitialCommands (m Model ) []tea.Cmd {
218
89
var cmds []tea.Cmd
219
- for _ , clusterNamespaces := range m .allClusterNamespaces {
90
+ for _ , clusterNamespaces := range m .client . AllClusterNamespaces () {
220
91
for _ , namespace := range clusterNamespaces .Namespaces {
221
92
cmds = append (cmds , command .GetContainerListenerCmd (
222
93
m .client ,
@@ -237,42 +108,3 @@ func createInitialCommands(m Model) []tea.Cmd {
237
108
238
109
return cmds
239
110
}
240
-
241
- // getKubeConfig gets kubeconfig, accounting for multiple file paths
242
- func getKubeConfig (kubeConfigPath string ) (api.Config , * clientcmd.ClientConfigLoadingRules , error ) {
243
- loadingRules := clientcmd .NewDefaultClientConfigLoadingRules ()
244
- kubeconfigPaths := strings .Split (kubeConfigPath , string (os .PathListSeparator ))
245
- dev .Debug (fmt .Sprintf ("kubeconfig paths: %v" , kubeconfigPaths ))
246
-
247
- loadingRules .Precedence = kubeconfigPaths
248
- clientConfig := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (loadingRules , nil )
249
- rawKubeConfig , err := clientConfig .RawConfig ()
250
- if err != nil {
251
- return api.Config {}, loadingRules , fmt .Errorf ("failed to load kubeconfig: %w" , err )
252
- }
253
- return rawKubeConfig , loadingRules , nil
254
- }
255
-
256
- func getContexts (contextString string , config api.Config ) ([]string , error ) {
257
- contextsString := strings .Trim (strings .TrimSpace (contextString ), "," )
258
- var contexts []string
259
- if len (contextsString ) > 0 {
260
- contexts = strings .Split (contextsString , "," )
261
- }
262
-
263
- if len (contexts ) == 0 && config .CurrentContext != "" {
264
- contexts = []string {config .CurrentContext }
265
- }
266
-
267
- if len (contexts ) == 0 {
268
- return nil , fmt .Errorf ("no contexts specified and no current context found in kubeconfig" )
269
- }
270
-
271
- for _ , c := range contexts {
272
- if _ , exists := config .Contexts [c ]; ! exists {
273
- return nil , fmt .Errorf ("context %s not found in kubeconfig" , c )
274
- }
275
- }
276
-
277
- return contexts , nil
278
- }
0 commit comments