@@ -10,13 +10,13 @@ import (
10
10
"net/http"
11
11
"net/url"
12
12
"os"
13
+ "os/exec"
13
14
"os/signal"
14
15
"strconv"
15
16
"strings"
16
17
"sync"
17
18
"time"
18
19
19
- "github.com/segmentio/kubectl-curl/curl"
20
20
"github.com/spf13/pflag"
21
21
corev1 "k8s.io/api/core/v1"
22
22
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -27,6 +27,8 @@ import (
27
27
"k8s.io/client-go/rest"
28
28
"k8s.io/client-go/tools/portforward"
29
29
"k8s.io/client-go/transport/spdy"
30
+
31
+ "github.com/segmentio/kubectl-curl/curl"
30
32
)
31
33
32
34
var (
36
38
debug bool
37
39
options string
38
40
flags * pflag.FlagSet
41
+ cflags * pflag.FlagSet
39
42
config * genericclioptions.ConfigFlags
40
43
)
41
44
@@ -48,8 +51,9 @@ func init() {
48
51
49
52
flags = pflag .NewFlagSet ("kubectl curl" , pflag .ExitOnError )
50
53
flags .BoolVarP (& help , "help" , "h" , false , "Prints the kubectl plugin help." )
51
- flags .BoolVarP (& debug , "debug" , "" , false , "Enable debug mode to print more details about the kubectl command execution." )
52
-
54
+ flags .BoolVarP (& debug , "debug" , "" , false ,
55
+ "Enable debug mode to print more details about the kubectl command execution." )
56
+ cflags = pflag .NewFlagSet ("curl" , pflag .ExitOnError ) // curl-only FlagSet
53
57
for _ , opt := range curlOptions {
54
58
name := strings .TrimPrefix (opt .Name , "--" )
55
59
short := strings .TrimPrefix (opt .Short , "-" )
@@ -69,13 +73,15 @@ func init() {
69
73
}
70
74
71
75
flag := flags .VarPF (opt .Value , name , short , opt .Help )
76
+ cflag := cflags .VarPF (opt .Value , name , short , opt .Help )
72
77
if curl .IsBoolFlag (opt .Value ) {
73
78
flag .NoOptDefVal = "true"
79
+ cflag .NoOptDefVal = "true"
74
80
}
75
81
}
76
82
77
83
config = genericclioptions .NewConfigFlags (false )
78
- config .AddFlags (flags )
84
+ config .AddFlags (flags ) // adds k8s config flags to flags
79
85
options = flags .FlagUsages ()
80
86
}
81
87
@@ -90,7 +96,25 @@ func main() {
90
96
}
91
97
92
98
func run (ctx context.Context ) error {
93
- flags .Parse (os .Args [1 :])
99
+ cArgs := make ([]string , 0 )
100
+ flags .ParseAll (os .Args [1 :], func (flag * pflag.Flag , value string ) error {
101
+ if flag .Name == "silent" {
102
+ return nil // --silent is added later to all curl arguments so don't add here
103
+ }
104
+
105
+ // if it's a curl flag, save the full name & value to pass as arguments later
106
+ found := cflags .Lookup (flag .Name )
107
+ if found != nil {
108
+ if flag .Value .Type () == "bool" {
109
+ cArgs = append (cArgs , "--" + flag .Name )
110
+ } else {
111
+ cArgs = append (cArgs , "--" + flag .Name )
112
+ cArgs = append (cArgs , value )
113
+ }
114
+ }
115
+
116
+ return flags .Set (flag .Name , value )
117
+ })
94
118
95
119
if help {
96
120
fmt .Print (usageAndOptions ("Run curl against kubernetes pods" ))
@@ -223,21 +247,36 @@ func run(ctx context.Context) error {
223
247
}
224
248
225
249
requestURL .Host = net .JoinHostPort ("localhost" , strconv .Itoa (int (localPort )))
226
- options : = append (curlOptions ,
227
- // The -s option is taken by -s,--server from the default kubectl
228
- // configuration. Force --silent because we don't really need to
229
- // print the dynamic progress view for the scenarios in which this
230
- // plugin is useful for.
231
- curl . Silent ( true ),
232
- )
233
- cmd := curl . Command (ctx , requestURL . String (), options ... )
250
+ cArgs = append (cArgs , requestURL . String ())
251
+ // The -s option is taken by -s,--server from the default kubectl
252
+ // configuration. Force --silent because we don't really need to
253
+ // print the dynamic progress view for the scenarios in which this
254
+ // plugin is useful for.
255
+ cArgs = append ( cArgs , "--silent" )
256
+
257
+ cmd := exec . CommandContext (ctx , "curl" , cArgs ... )
234
258
cmd .Stdin = os .Stdin
235
259
cmd .Stdout = os .Stdout
236
260
cmd .Stderr = os .Stderr
237
- log .Printf ("curl %s" , strings . Join (cmd .Args [1 :], " \n \t " ))
261
+ log .Printf ("curl %s" , prettyArgs (cmd .Args [1 :]))
238
262
return cmd .Run ()
239
263
}
240
264
265
+ func prettyArgs (slice []string ) string {
266
+ out := ""
267
+ for i , s := range slice {
268
+ if strings .Contains (s , " " ) {
269
+ out += fmt .Sprintf ("%q" , s ) // add quotes when known
270
+ } else {
271
+ out += s
272
+ }
273
+ if i != len (slice )- 1 {
274
+ out += " " // separate elements with space
275
+ }
276
+ }
277
+ return out
278
+ }
279
+
241
280
func selectContainerPort (pod * corev1.Pod , containerName , portName string ) (selectedContainerName string , selectedContainerPort corev1.ContainerPort , err error ) {
242
281
for _ , container := range pod .Spec .Containers {
243
282
if containerName != "" && container .Name != containerName {
@@ -248,7 +287,8 @@ func selectContainerPort(pod *corev1.Pod, containerName, portName string) (selec
248
287
continue
249
288
}
250
289
if selectedContainerPort .Name != "" {
251
- err = fmt .Errorf ("pod %[1]s has multiple containers with a %[2]s port, use kubectl %[1]s [container] to specify which one to profile" , pod .Name , portName )
290
+ err = fmt .Errorf ("pod %[1]s has multiple containers with a %[2]s port, use kubectl %[1]s [container] to specify which one to profile" ,
291
+ pod .Name , portName )
252
292
return
253
293
}
254
294
selectedContainerName = container .Name
0 commit comments