@@ -17,18 +17,124 @@ limitations under the License.
17
17
package cmd
18
18
19
19
import (
20
+ "context"
21
+ "fmt"
22
+ "os"
23
+ "time"
24
+
20
25
"github.com/spf13/cobra"
26
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
+ "k8s.io/client-go/kubernetes"
28
+ "k8s.io/client-go/rest"
29
+ "k8s.io/client-go/tools/clientcmd"
21
30
cliflag "k8s.io/component-base/cli/flag"
22
31
"k8s.io/component-base/logs"
23
32
kubecmd "k8s.io/kubectl/pkg/cmd"
24
33
)
25
34
35
+ const (
36
+ cmNamespace = "d8-system"
37
+ cmName = "debug-container"
38
+ cmImageKey = "image"
39
+ )
40
+
41
+ func getKubeConfig (kubeconfigPath string ) (* rest.Config , error ) {
42
+ loadingRules := clientcmd .NewDefaultClientConfigLoadingRules ()
43
+
44
+ if kubeconfigPath != "" {
45
+ loadingRules .ExplicitPath = kubeconfigPath
46
+ }
47
+
48
+ configOverrides := & clientcmd.ConfigOverrides {}
49
+ kubeConfig := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (loadingRules , configOverrides )
50
+
51
+ config , err := kubeConfig .ClientConfig ()
52
+ if err != nil {
53
+ return nil , fmt .Errorf ("failed to load kubernetes config: %w" , err )
54
+ }
55
+
56
+ return config , nil
57
+ }
58
+
59
+ func getDebugImage (cmd * cobra.Command ) (string , error ) {
60
+ kubeconfigPath , err := cmd .Flags ().GetString ("kubeconfig" )
61
+ if err != nil {
62
+ return "" , fmt .Errorf ("failed to get kubeconfig flag: %w" , err )
63
+ }
64
+
65
+ config , err := getKubeConfig (kubeconfigPath )
66
+ if err != nil {
67
+ return "" , fmt .Errorf ("failed to setup Kubernetes client: %w" , err )
68
+ }
69
+
70
+ kubeCl , err := kubernetes .NewForConfig (config )
71
+ if err != nil {
72
+ return "" , fmt .Errorf ("failed to create Kubernetes client: %w" , err )
73
+ }
74
+
75
+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
76
+ defer cancel ()
77
+ configMap , err := kubeCl .CoreV1 ().ConfigMaps (cmNamespace ).Get (ctx , cmName , v1.GetOptions {})
78
+ if err != nil {
79
+ return "" , fmt .Errorf ("failed to get ConfigMap %s/%s: %w" , cmNamespace , cmName , err )
80
+ }
81
+
82
+ imageName , ok := configMap .Data [cmImageKey ]
83
+ if ! ok {
84
+ return "" , fmt .Errorf ("key '%s' not found in ConfigMap %s/%s" , cmImageKey , cmNamespace , cmName )
85
+ }
86
+
87
+ if imageName == "" {
88
+ return "" , fmt .Errorf ("image name is empty in ConfigMap %s/%s" , cmNamespace , cmName )
89
+ }
90
+
91
+ return imageName , nil
92
+ }
93
+
26
94
func init () {
27
95
kubectlCmd := kubecmd .NewDefaultKubectlCommand ()
28
96
kubectlCmd .Use = "k"
29
97
kubectlCmd .Aliases = []string {"kubectl" }
30
98
kubectlCmd = ReplaceCommandName ("kubectl" , "d8 k" , kubectlCmd )
31
99
100
+ var debugCmd * cobra.Command
101
+ for _ , cmd := range kubectlCmd .Commands () {
102
+ if cmd .Name () == "debug" {
103
+ debugCmd = cmd
104
+ break
105
+ }
106
+ }
107
+
108
+ if debugCmd != nil {
109
+ if imageFlag := debugCmd .Flags ().Lookup ("image" ); imageFlag != nil {
110
+ imageFlag .Usage = "Container image to use for debug container. If not specified, the platform's recommended image will be used."
111
+ }
112
+ }
113
+
114
+ rootCmd .PersistentFlags ().String ("kubeconfig" , "" , "Path to the kubeconfig file" )
115
+
116
+ originalPersistentPreRunE := kubectlCmd .PersistentPreRunE
117
+ kubectlCmd .PersistentPreRunE = func (cmd * cobra.Command , args []string ) error {
118
+ if cmd .Name () == "debug" || (cmd .Parent () != nil && cmd .Parent ().Name () == "debug" ) {
119
+ imageFlag := cmd .Flags ().Lookup ("image" )
120
+ if imageFlag != nil && imageFlag .Value .String () == "" {
121
+ debugImage , err := getDebugImage (cmd )
122
+ if err != nil {
123
+ fmt .Fprintf (os .Stderr , "Warning: cannot get debug container image from cluster: %v\n " , err )
124
+ fmt .Fprintf (os .Stderr , "Continuing with default kubectl behavior...\n " )
125
+ } else {
126
+ fmt .Fprintf (os .Stderr , "Using debug container image: %s\n " , debugImage )
127
+ cmd .Flags ().Set ("image" , debugImage )
128
+ }
129
+ }
130
+ }
131
+
132
+ if originalPersistentPreRunE != nil {
133
+ return originalPersistentPreRunE (cmd , args )
134
+ }
135
+ return nil
136
+ }
137
+
32
138
// Based on https://github.com/kubernetes/kubernetes/blob/v1.29.3/staging/src/k8s.io/component-base/cli/run.go#L88
33
139
34
140
kubectlCmd .SetGlobalNormalizationFunc (cliflag .WordSepNormalizeFunc )
0 commit comments