@@ -25,93 +25,115 @@ import (
2525 v1 "k8s.io/api/core/v1"
2626 "sigs.k8s.io/controller-runtime/pkg/client"
2727
28- "github.com/erda-project/erda/apistructs"
2928 "github.com/erda-project/kubeprober/pkg/probe-master/k8sclient"
3029 dialclient "github.com/erda-project/kubeprober/pkg/probe-master/tunnel-client"
3130)
3231
32+ const (
33+ probeAgentLabelKey = "app"
34+ probeAgentLabelValue = "probe-agent"
35+ probeAgentContainer = "probe-agent"
36+ execCommandScript = "kubectl-shell.sh"
37+ )
38+
3339func ClusterConsole (rw http.ResponseWriter , req * http.Request ) {
34- // TODO make blow correct
35- vars := mux .Vars (req )
36- clusterName := vars ["clusterName" ]
40+ clusterName := mux .Vars (req )["clusterName" ]
41+ if clusterName == "" {
42+ http .Error (rw , "cluster name is required" , http .StatusNotFound )
43+ return
44+ }
3745
3846 cluster , err := k8sclient .GetCluster (clusterName )
3947 if err != nil {
40- errMsg := fmt .Sprintf ("[cluster console] failed to list cluster with name: %s" , clusterName )
41- logrus .Errorf (errMsg )
42- rw .Write ([]byte (errMsg ))
43- rw .WriteHeader (http .StatusInternalServerError )
48+ logrus .Errorf ("[cluster console] failed to get cluster %s: %v" , clusterName , err )
49+ http .Error (rw , "Internal server error" , http .StatusInternalServerError )
4450 return
4551 }
4652 if cluster == nil {
47- errMsg := fmt .Sprintf ("[cluster console] failed to find cluster with name: %s\n " , clusterName )
48- rw .Write ([]byte (errMsg ))
49- rw .WriteHeader (http .StatusBadRequest )
50- return
51- }
52-
53- token := cluster .Spec .ClusterConfig .Token
54- if token == "" {
55- errMsg := fmt .Sprintf ("[cluster console] invalid token for cluster with name: %s\n " , clusterName )
56- rw .Write ([]byte (errMsg ))
57- rw .WriteHeader (http .StatusInternalServerError )
53+ http .Error (rw , fmt .Sprintf ("cluster %s not found" , clusterName ), http .StatusBadRequest )
5854 return
5955 }
6056
61- t , err := base64 . StdEncoding . DecodeString ( cluster .Spec .ClusterConfig .Token )
57+ token , err := decodeClusterToken ( clusterName , cluster .Spec .ClusterConfig .Token )
6258 if err != nil {
63- errMsg := fmt .Sprintf ("[cluster console] invalid token for cluster: %s\n " , clusterName )
64- rw .Write ([]byte (errMsg ))
65- rw .WriteHeader (http .StatusInternalServerError )
59+ logrus .Errorf ("[cluster console] invalid token for cluster %s: %v" , clusterName , err )
60+ http .Error (rw , "Internal server error" , http .StatusInternalServerError )
6661 return
6762 }
68- token = string (t )
6963
7064 clusterclient , err := dialclient .GenerateProbeClient (cluster )
7165 if err != nil {
72- errMsg := fmt .Sprintf ("[cluster console] invalid token for cluster with name: %s\n " , clusterName )
73- rw .Write ([]byte (errMsg ))
74- rw .WriteHeader (http .StatusInternalServerError )
66+ logrus .Errorf ("[cluster console] failed to build k8s client for cluster %s: %v" , clusterName , err )
67+ http .Error (rw , "Internal server error" , http .StatusInternalServerError )
7568 return
7669 }
77- podList := & v1.PodList {}
7870
79- err = clusterclient .List (context .Background (), podList ,
80- client .InNamespace (cluster .Spec .ClusterConfig .ProbeNamespaces ),
81- client.MatchingLabels {"app" : "probe-agent" })
71+ pod , err := findRunningProbeAgent (req .Context (), clusterclient , cluster .Spec .ClusterConfig .ProbeNamespaces )
8272 if err != nil {
83- errMsg := fmt .Sprintf ("[cluster console] failed to find probe-agent pod for cluster with name: %s\n " , clusterName )
84- rw .Write ([]byte (errMsg ))
85- rw .WriteHeader (http .StatusInternalServerError )
73+ logrus .Errorf ("[cluster console] failed to list probe-agent pods for cluster %s: %v" , clusterName , err )
74+ http .Error (rw , "Internal server error" , http .StatusInternalServerError )
75+ return
76+ }
77+ if pod == nil {
78+ logrus .Errorf ("failed to find a ready probe-agent pod for cluster %s" , clusterName )
79+ http .Error (rw , fmt .Sprintf ("cluster %s does not have a ready probe-agent pod" , clusterName ), http .StatusInternalServerError )
8680 return
8781 }
8882
89- for _ , pod := range podList .Items {
90- if pod .Status .Phase != v1 .PodRunning {
91- continue
92- }
83+ req .URL .Path = execURLPath (clusterName , pod .Namespace , pod .Name )
84+ req .URL .RawQuery = execQuery (token ).Encode ()
85+
86+ if proxyManager == nil {
87+ logrus .Errorf ("proxy manager not initialized for cluster %s" , clusterName )
88+ http .Error (rw , "Internal server error" , http .StatusInternalServerError )
89+ return
90+ }
9391
94- vars := url.Values {}
95- vars .Add ("container" , "probe-agent" )
96- vars .Add ("stdout" , "1" )
97- vars .Add ("stdin" , "1" )
98- vars .Add ("stderr" , "1" )
99- vars .Add ("tty" , "1" )
100- vars .Add ("command" , "kubectl-shell.sh" )
101- vars .Add ("command" , token )
92+ proxyManager .ProxyRequest (rw , req , clusterName )
93+ }
10294
103- path := fmt .Sprintf ("/api/k8s/clusters/%s/api/v1/namespaces/%s/pods/%s/exec" , clusterName , pod .Namespace , pod .Name )
95+ func decodeClusterToken (clusterName , encoded string ) (string , error ) {
96+ if encoded == "" {
97+ return "" , fmt .Errorf ("empty token for cluster %s" , clusterName )
98+ }
99+ decoded , err := base64 .StdEncoding .DecodeString (encoded )
100+ if err != nil {
101+ return "" , err
102+ }
103+ return string (decoded ), nil
104+ }
104105
105- req .URL .Path = path
106- req .URL .RawQuery = vars .Encode ()
106+ func findRunningProbeAgent (ctx context.Context , c client.Client , namespace string ) (* v1.Pod , error ) {
107+ podList := & v1.PodList {}
108+ err := c .List (ctx , podList ,
109+ client .InNamespace (namespace ),
110+ client.MatchingLabels {probeAgentLabelKey : probeAgentLabelValue })
111+ if err != nil {
112+ return nil , err
113+ }
107114
108- a .ServeHTTP (rw , req )
109- return
115+ for i := range podList .Items {
116+ pod := & podList .Items [i ]
117+ if pod .Status .Phase == v1 .PodRunning {
118+ return pod , nil
119+ }
110120 }
111121
112- logrus .Errorf ("failed to find a ready probe-agent pod for cluster %s" , clusterName )
113- rw .WriteHeader (http .StatusInternalServerError )
114- rw .Write (apistructs .NewSteveError (apistructs .ServerError ,
115- fmt .Sprintf ("cluster %s does not have a ready probe-agent pod" , clusterName )).JSON ())
116- return
122+ return nil , nil
123+ }
124+
125+ func execQuery (token string ) url.Values {
126+ query := url.Values {}
127+ query .Add ("container" , probeAgentContainer )
128+ query .Add ("stdout" , "1" )
129+ query .Add ("stdin" , "1" )
130+ query .Add ("stderr" , "1" )
131+ query .Add ("tty" , "1" )
132+ query .Add ("command" , execCommandScript )
133+ query .Add ("command" , token )
134+ return query
135+ }
136+
137+ func execURLPath (clusterName , namespace , podName string ) string {
138+ return fmt .Sprintf ("/api/k8s/clusters/%s/api/v1/namespaces/%s/pods/%s/exec" , clusterName , namespace , podName )
117139}
0 commit comments