Skip to content

Commit 4e314cd

Browse files
authored
Merge pull request #1429 from laozc/windows-info
Fixes invalid JSON in crictl info
2 parents 31ae1ac + 39a77d4 commit 4e314cd

File tree

2 files changed

+123
-15
lines changed

2 files changed

+123
-15
lines changed

Diff for: cmd/crictl/util.go

+26-15
Original file line numberDiff line numberDiff line change
@@ -245,37 +245,48 @@ func outputStatusInfo(status, handlers string, info map[string]string, format st
245245
}
246246
sort.Strings(keys)
247247

248-
jsonInfo := "{" + "\"status\":" + status + ","
249-
if handlers != "" {
250-
jsonInfo += "\"runtimeHandlers\":" + handlers + ","
248+
infoMap := map[string]interface{}{}
249+
250+
var statusVal map[string]interface{}
251+
err := json.Unmarshal([]byte(status), &statusVal)
252+
if err != nil {
253+
return err
254+
}
255+
infoMap["status"] = statusVal
256+
257+
var handlersVal map[string]interface{}
258+
err = json.Unmarshal([]byte(handlers), &handlersVal)
259+
if err != nil {
260+
return err
251261
}
262+
if handlersVal != nil {
263+
infoMap["runtimeHandlers"] = handlersVal
264+
}
265+
252266
for _, k := range keys {
253-
var res interface{}
254-
// We attempt to convert key into JSON if possible else use it directly
255-
if err := json.Unmarshal([]byte(info[k]), &res); err != nil {
256-
jsonInfo += "\"" + k + "\"" + ":" + "\"" + info[k] + "\","
257-
} else {
258-
jsonInfo += "\"" + k + "\"" + ":" + info[k] + ","
259-
}
267+
infoMap[k] = strings.Trim(info[k], "\"")
268+
}
269+
270+
jsonInfo, err := json.Marshal(infoMap)
271+
if err != nil {
272+
return err
260273
}
261-
jsonInfo = jsonInfo[:len(jsonInfo)-1]
262-
jsonInfo += "}"
263274

264275
switch format {
265276
case "yaml":
266-
yamlInfo, err := yaml.JSONToYAML([]byte(jsonInfo))
277+
yamlInfo, err := yaml.JSONToYAML(jsonInfo)
267278
if err != nil {
268279
return err
269280
}
270281
fmt.Println(string(yamlInfo))
271282
case "json":
272283
var output bytes.Buffer
273-
if err := json.Indent(&output, []byte(jsonInfo), "", " "); err != nil {
284+
if err := json.Indent(&output, jsonInfo, "", " "); err != nil {
274285
return err
275286
}
276287
fmt.Println(output.String())
277288
case "go-template":
278-
output, err := tmplExecuteRawJSON(tmplStr, jsonInfo)
289+
output, err := tmplExecuteRawJSON(tmplStr, string(jsonInfo))
279290
if err != nil {
280291
return err
281292
}

Diff for: cmd/crictl/util_test.go

+97
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"io"
21+
"os"
22+
"strings"
2023
"testing"
24+
25+
. "github.com/onsi/gomega"
2126
)
2227

2328
func TestNameFilterByRegex(t *testing.T) {
@@ -64,7 +69,99 @@ func TestNameFilterByRegex(t *testing.T) {
6469
if r != tc.isMatch {
6570
t.Errorf("expected matched to be %v; actual result is %v", tc.isMatch, r)
6671
}
72+
})
73+
}
74+
}
6775

76+
func TestOutputStatusInfo(t *testing.T) {
77+
const (
78+
statusResponse = `{"conditions":[{
79+
"message": "no network config found in C:\\Program Files",
80+
"reason": "NetworkPluginNotReady",
81+
"status": false,
82+
"type": "NetworkReady"
83+
}]}`
84+
)
85+
testCases := []struct {
86+
name string
87+
status string
88+
handlers string
89+
info map[string]string
90+
format string
91+
tmplStr string
92+
expectedOut string
93+
}{
94+
{
95+
name: "YAML format",
96+
status: statusResponse,
97+
handlers: `{"handlers":["handler1","handler2"]}`,
98+
info: map[string]string{"key1": "value1", "key2": "/var/lib"},
99+
format: "yaml",
100+
tmplStr: "",
101+
expectedOut: "key1: value1\nkey2: /var/lib\nruntimeHandlers:\n handlers:\n - handler1\n - handler2\nstatus:\n conditions:\n - message: no network config found in C:\\Program Files\n reason: NetworkPluginNotReady\n status: false\n type: NetworkReady",
102+
},
103+
{
104+
name: "JSON format",
105+
status: statusResponse,
106+
handlers: `{"handlers":["handler1","handler2"]}`,
107+
info: map[string]string{"key1": "\"value1\"", "key2": "\"C:\\ProgramFiles\""},
108+
format: "json",
109+
tmplStr: "",
110+
expectedOut: "{\n \"key1\": \"value1\",\n \"key2\": \"C:\\\\ProgramFiles\",\n \"runtimeHandlers\": {\n \"handlers\": [\n \"handler1\",\n \"handler2\"\n ]\n },\n \"status\": {\n \"conditions\": [\n {\n \"message\": \"no network config found in C:\\\\Program Files\",\n \"reason\": \"NetworkPluginNotReady\",\n \"status\": false,\n \"type\": \"NetworkReady\"\n }\n ]\n }\n}",
111+
},
112+
{
113+
name: "Go template format",
114+
status: statusResponse,
115+
handlers: `{"handlers":["handler1","handler2"]}`,
116+
info: map[string]string{"key1": "value1", "key2": "value2"},
117+
format: "go-template",
118+
tmplStr: `NetworkReady: {{ (index .status.conditions 0).status }}`,
119+
expectedOut: "NetworkReady: false",
120+
},
121+
}
122+
123+
// Run tests
124+
for _, tc := range testCases {
125+
t.Run(tc.name, func(t *testing.T) {
126+
captureOutput := func(f func() error) (string, error) {
127+
var err error
128+
old := os.Stdout
129+
130+
r, w, _ := os.Pipe()
131+
os.Stdout = w
132+
defer func() {
133+
os.Stdout = old
134+
}()
135+
136+
err = f()
137+
if err != nil {
138+
return "", err
139+
}
140+
141+
err = w.Close()
142+
if err != nil {
143+
return "", err
144+
}
145+
146+
out, err := io.ReadAll(r)
147+
return strings.TrimRight(string(out), "\n"), err
148+
}
149+
150+
outStr, err := captureOutput(func() error {
151+
err := outputStatusInfo(tc.status, tc.handlers, tc.info, tc.format, tc.tmplStr)
152+
if err != nil {
153+
t.Errorf("Unexpected error: %v", err)
154+
}
155+
return nil
156+
})
157+
158+
if err != nil {
159+
Expect(err).To(BeNil())
160+
}
161+
162+
if outStr != tc.expectedOut {
163+
t.Errorf("Expected output:\n%s\nGot:\n%s", tc.expectedOut, outStr)
164+
}
68165
})
69166
}
70167
}

0 commit comments

Comments
 (0)