Skip to content

Commit c6d6bcc

Browse files
committed
fix get subcommand
1 parent 55166e5 commit c6d6bcc

File tree

6 files changed

+42
-20
lines changed

6 files changed

+42
-20
lines changed

Readme.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ This mode is invoked by calling the `get` subcommand, i.e `kubectl neat get ...`
5959

6060
Examples:
6161
```bash
62-
kubectl neat get pod mypod -oyaml
63-
kubectl neat get svc -n default myservice --output json
62+
kubectl neat get -- pod mypod -oyaml
63+
kubectl neat get -- svc -n default myservice --output json
6464
```
6565

6666
# How it works

cmd/cmd.go

+35-13
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,42 @@ var kubectl string = "kubectl"
8383

8484
var getCmd = &cobra.Command{
8585
Use: "get",
86-
Example: `kubectl neat get pod mypod -oyaml
87-
kubectl neat get svc -n default myservice --output json`,
88-
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true}, //don't validate kubectl get's flags
86+
Example: `kubectl neat get -- pod mypod -oyaml
87+
kubectl neat get -- svc -n default myservice --output json`,
88+
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true}, //don't try to validate kubectl get's flags
8989
RunE: func(cmd *cobra.Command, args []string) error {
90-
var in, out []byte
90+
var out []byte
9191
var err error
92-
cmdArgs := append([]string{"get", "-o"}, *outputFormat)
93-
cmdArgs = append(cmdArgs, args...)
92+
//reset defaults
93+
//there are two output settings in this subcommand: kubectl get's and kubectl-neat's
94+
//any combination of those can be provided by using the output flag in either side of the --
95+
//the most efficient is kubectl: json, kubectl-neat: yaml
96+
//0--0->Y--J #choose what's best for us
97+
//0--Y->Y--Y #user did specify output in kubectl, so respect that
98+
//0--J->J--J #user did specify output in kubectl, so respect that
99+
//Y--0->Y--J #user doesn't care about kubectl so use json but convert back
100+
//J--0->J--J #user expects json so use it for foth
101+
//if the user specified both side we can't touch it
102+
103+
//the desired kubectl get output is always json, unless it was explicitly set by the user to yaml in which case the arg is overriden when concatenating the args later
104+
cmdArgs := append([]string{"get", "-o", "json"}, args...)
94105
kubectlCmd := exec.Command(kubectl, cmdArgs...)
95106
kres, err := kubectlCmd.CombinedOutput()
96107
if err != nil {
97-
return err
108+
return fmt.Errorf("Error invoking kubectl as %v %v", kubectlCmd.Args, err)
98109
}
99-
in = kres
100-
101-
out, err = NeatYAMLOrJSON(in, *outputFormat)
110+
//handle the case of 0--J->J--J
111+
outFormat := *outputFormat
112+
kubeout := "yaml"
113+
for _, arg := range args {
114+
if arg == "json" || arg == "ojson" {
115+
outFormat = "json"
116+
}
117+
}
118+
if !cmd.Flag("output").Changed && kubeout == "json" {
119+
outFormat = "json"
120+
}
121+
out, err = NeatYAMLOrJSON(kres, outFormat)
102122
if err != nil {
103123
return err
104124
}
@@ -107,12 +127,14 @@ kubectl neat get svc -n default myservice --output json`,
107127
},
108128
}
109129

130+
func isJSON(s []byte) bool {
131+
return bytes.HasPrefix(bytes.TrimLeftFunc(s, unicode.IsSpace), []byte{'{'})
132+
}
133+
110134
// NeatYAMLOrJSON converts 'in' to json if needed, invokes neat, and converts back if needed according the the outputFormat argument: yaml/json/same
111135
func NeatYAMLOrJSON(in []byte, outputFormat string) (out []byte, err error) {
112136
var injson, outjson string
113-
114-
// detect if 'in' is yaml or json
115-
itsYaml := !bytes.HasPrefix(bytes.TrimLeftFunc(in, unicode.IsSpace), []byte{'{'})
137+
itsYaml := !isJSON(in)
116138
if itsYaml {
117139
injsonbytes, err := yaml.YAMLToJSON(in)
118140
if err != nil {

cmd/cmd_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func TestGetCmd(t *testing.T) {
134134
{
135135
args: []string{""},
136136
assertError: func(err error) bool {
137-
return fmt.Sprintf("%T", err) == "*exec.ExitError"
137+
return strings.HasPrefix(err.Error(), "Error invoking kubectl")
138138
},
139139
expOut: "",
140140
expErr: "",

krew-template.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ spec:
1212
removing default values, runtime information, and other internal fields.
1313
Examples:
1414
`$ kubectl get pod mypod -o yaml | kubectl neat`
15-
`$ kubectl neat get pod mypod -o yaml`
15+
`$ kubectl neat get -- pod mypod -o yaml`
1616
platforms:
1717
- selector:
1818
matchLabels:

test/e2e-krew.bats

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function teardown() {
1414
}
1515

1616
@test "krew install" {
17-
run2 kubectl "$plugin" get svc kubernetes -n default
17+
run2 kubectl "$plugin" get -- svc kubernetes -n default
1818
[ "$status" -eq 0 ]
1919
[ "${stdoutLines[1]}" = "kind: Service" ]
2020
}

test/e2e-kubectl.bats

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ function teardown() {
1818
}
1919

2020
@test "plugin - json" {
21-
run2 kubectl "$plugin_name" get -o json svc kubernetes -n default
21+
run2 kubectl "$plugin_name" get -o json -- svc kubernetes -n default
2222
[ "$status" -eq 0 ]
2323
[[ $stdout == "{"* ]]
2424
}
2525

2626
@test "plugin - yaml" {
27-
run2 kubectl "$plugin_name" get svc kubernetes -n default -o yaml
27+
run2 kubectl "$plugin_name" get -- svc kubernetes -n default
2828
[ "$status" -eq 0 ]
2929
[[ $stdout == "apiVersion"* ]]
3030
}

0 commit comments

Comments
 (0)