Skip to content

Commit e8701a2

Browse files
bartleygAchille
andauthored
Fix curl options and allow multiple of the same option (#10)
* fix curl options and allow multiple of the same option * Apply suggestions from code review Co-authored-by: Achille <achille@segment.com> Co-authored-by: Achille <achille@segment.com>
1 parent 4a3f1bb commit e8701a2

File tree

3 files changed

+56
-35
lines changed

3 files changed

+56
-35
lines changed

curl.go

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import (
1010
"net/http"
1111
"net/url"
1212
"os"
13+
"os/exec"
1314
"os/signal"
1415
"strconv"
1516
"strings"
1617
"sync"
1718
"time"
1819

19-
"github.com/segmentio/kubectl-curl/curl"
2020
"github.com/spf13/pflag"
2121
corev1 "k8s.io/api/core/v1"
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -27,6 +27,8 @@ import (
2727
"k8s.io/client-go/rest"
2828
"k8s.io/client-go/tools/portforward"
2929
"k8s.io/client-go/transport/spdy"
30+
31+
"github.com/segmentio/kubectl-curl/curl"
3032
)
3133

3234
var (
@@ -36,6 +38,7 @@ var (
3638
debug bool
3739
options string
3840
flags *pflag.FlagSet
41+
cflags *pflag.FlagSet
3942
config *genericclioptions.ConfigFlags
4043
)
4144

@@ -48,8 +51,9 @@ func init() {
4851

4952
flags = pflag.NewFlagSet("kubectl curl", pflag.ExitOnError)
5053
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
5357
for _, opt := range curlOptions {
5458
name := strings.TrimPrefix(opt.Name, "--")
5559
short := strings.TrimPrefix(opt.Short, "-")
@@ -69,13 +73,15 @@ func init() {
6973
}
7074

7175
flag := flags.VarPF(opt.Value, name, short, opt.Help)
76+
cflag := cflags.VarPF(opt.Value, name, short, opt.Help)
7277
if curl.IsBoolFlag(opt.Value) {
7378
flag.NoOptDefVal = "true"
79+
cflag.NoOptDefVal = "true"
7480
}
7581
}
7682

7783
config = genericclioptions.NewConfigFlags(false)
78-
config.AddFlags(flags)
84+
config.AddFlags(flags) // adds k8s config flags to flags
7985
options = flags.FlagUsages()
8086
}
8187

@@ -90,7 +96,25 @@ func main() {
9096
}
9197

9298
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+
})
94118

95119
if help {
96120
fmt.Print(usageAndOptions("Run curl against kubernetes pods"))
@@ -223,21 +247,36 @@ func run(ctx context.Context) error {
223247
}
224248

225249
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...)
234258
cmd.Stdin = os.Stdin
235259
cmd.Stdout = os.Stdout
236260
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:]))
238262
return cmd.Run()
239263
}
240264

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+
241280
func selectContainerPort(pod *corev1.Pod, containerName, portName string) (selectedContainerName string, selectedContainerPort corev1.ContainerPort, err error) {
242281
for _, container := range pod.Spec.Containers {
243282
if containerName != "" && container.Name != containerName {
@@ -248,7 +287,8 @@ func selectContainerPort(pod *corev1.Pod, containerName, portName string) (selec
248287
continue
249288
}
250289
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)
252292
return
253293
}
254294
selectedContainerName = container.Name

curl/basic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func (b *Bool) Set(value string) error {
2121
}
2222

2323
func (b Bool) Get() interface{} { return bool(b) }
24-
func (b Bool) Type() string { return "" }
24+
func (b Bool) Type() string { return "bool" }
2525
func (b Bool) String() string { return strconv.FormatBool(bool(b)) }
2626
func (b Bool) IsBoolFlag() bool { return true }
2727

curl/command.go

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)