diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 77f6b65d3dc..9feed5754c9 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -138,6 +138,19 @@ for version in "${kube_api_versions[@]}"; do output_service=$(kubectl get service frontend -o json --output-version=v1beta3 "${kube_flags[@]}") kubectl delete service frontend "${kube_flags[@]}" echo "${output_service}" | kubectl create -f - "${kube_flags[@]}" + kubectl create -f - "${kube_flags[@]}" << __EOF__ + { + "kind": "Service", + "apiVersion": "v1beta1", + "id": "service-${version}-test", + "port": 80, + "protocol": "TCP", + "labels": { + "name": "${version}" + } + } +__EOF__ + kubectl get services "something-${version}" "${kube_flags[@]}" kubectl get services "${kube_flags[@]}" kubectl delete service frontend "${kube_flags[@]}" diff --git a/pkg/kubectl/resource/visitor.go b/pkg/kubectl/resource/visitor.go index 7098ee8d214..46b2e0c74a2 100644 --- a/pkg/kubectl/resource/visitor.go +++ b/pkg/kubectl/resource/visitor.go @@ -337,7 +337,10 @@ type StreamVisitor struct { } // NewStreamVisitor creates a visitor that will return resources that were encoded into the provided -// stream. If ignoreErrors is set, unrecognized or invalid objects will be skipped and logged. +// stream. If ignoreErrors is set, unrecognized or invalid objects will be skipped and logged. An +// empty stream is treated as an error for now. +// TODO: convert ignoreErrors into a func(data, error, count) bool that consumers can use to decide +// what to do with ignored errors. func NewStreamVisitor(r io.Reader, mapper *Mapper, source string, ignoreErrors bool) Visitor { return &StreamVisitor{r, mapper, source, ignoreErrors} } @@ -356,7 +359,7 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error { info, err := v.InfoForData(ext.RawJSON, v.Source) if err != nil { if v.IgnoreErrors { - glog.V(2).Infof("Unable to read item from stream %q: %v", err) + glog.Warningf("Could not read an encoded object from %s: %v", v.Source, err) glog.V(4).Infof("Unreadable: %s", string(ext.RawJSON)) continue } diff --git a/pkg/util/yaml/decoder.go b/pkg/util/yaml/decoder.go index ccab145759e..e6e281b1c39 100644 --- a/pkg/util/yaml/decoder.go +++ b/pkg/util/yaml/decoder.go @@ -149,6 +149,6 @@ func guessJSONStream(r io.Reader, size int) (io.Reader, bool) { // Return true if the first non-whitespace bytes in buf is // prefix func hasPrefix(buf []byte, prefix []byte) bool { - buf = bytes.TrimLeftFunc(buf, unicode.IsSpace) - return bytes.HasPrefix(buf, prefix) + trim := bytes.TrimLeftFunc(buf, unicode.IsSpace) + return bytes.HasPrefix(trim, prefix) } diff --git a/pkg/util/yaml/decoder_test.go b/pkg/util/yaml/decoder_test.go index c590b5452f8..aa02d2853ba 100644 --- a/pkg/util/yaml/decoder_test.go +++ b/pkg/util/yaml/decoder_test.go @@ -61,6 +61,21 @@ func TestSplitYAMLDocument(t *testing.T) { } } +func TestGuessJSON(t *testing.T) { + if r, isJSON := guessJSONStream(bytes.NewReader([]byte(" \n{}")), 100); !isJSON { + t.Fatalf("expected stream to be JSON") + } else { + b := make([]byte, 30) + n, err := r.Read(b) + if err != nil || n != 4 { + t.Fatalf("unexpected body: %d / %v", n, err) + } + if string(b[:n]) != " \n{}" { + t.Fatalf("unexpected body: %q", string(b[:n])) + } + } +} + func TestScanYAML(t *testing.T) { s := bufio.NewScanner(bytes.NewReader([]byte(`--- stuff: 1 @@ -130,7 +145,10 @@ func TestYAMLOrJSONDecoder(t *testing.T) { {" \na: b", 2, false, false, []generic{ {"a": "b"}, }}, - {` \n{"a": "b"}`, 2, false, true, []generic{ + {" \n{\"a\": \"b\"}", 2, false, true, []generic{ + {"a": "b"}, + }}, + {" \n{\"a\": \"b\"}", 3, true, false, []generic{ {"a": "b"}, }}, {` {"a":"b"}`, 100, true, false, []generic{