diff --git a/pkg/util/yaml/decoder.go b/pkg/util/yaml/decoder.go index 7f06ba1bb3..a48a6ce864 100644 --- a/pkg/util/yaml/decoder.go +++ b/pkg/util/yaml/decoder.go @@ -20,7 +20,10 @@ import ( "bufio" "bytes" "encoding/json" + "fmt" "io" + "io/ioutil" + "strings" "unicode" "github.com/ghodss/yaml" @@ -203,7 +206,20 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error { d.decoder = NewYAMLToJSONDecoder(buffer) } } - return d.decoder.Decode(into) + err := d.decoder.Decode(into) + if jsonDecoder, ok := d.decoder.(*json.Decoder); ok { + if syntax, ok := err.(*json.SyntaxError); ok { + data, readErr := ioutil.ReadAll(jsonDecoder.Buffered()) + if readErr != nil { + glog.V(4).Infof("reading stream failed: %v", readErr) + } + js := string(data) + start := strings.LastIndex(js[:syntax.Offset], "\n") + 1 + line := strings.Count(js[:start], "\n") + return fmt.Errorf("json: line %d: %s", line, syntax.Error()) + } + } + return err } // GuessJSONStream scans the provided reader up to size, looking diff --git a/pkg/util/yaml/decoder_test.go b/pkg/util/yaml/decoder_test.go index e1e3f66095..047ea36036 100644 --- a/pkg/util/yaml/decoder_test.go +++ b/pkg/util/yaml/decoder_test.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "io" + "strings" "testing" ) @@ -125,6 +126,41 @@ stuff: 1 } } +func TestDecodeBrokenYAML(t *testing.T) { + s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`--- +stuff: 1 + test-foo: 1 + +--- + `)), 100) + obj := generic{} + err := s.Decode(&obj) + if err == nil { + t.Fatal("expected error with yaml: prefix, got no error") + } + if !strings.HasPrefix(err.Error(), "yaml: line 2:") { + t.Fatalf("expected %q to have 'yaml: line 2:' prefix", err.Error()) + } +} + +func TestDecodeBrokenJSON(t *testing.T) { + s := NewYAMLOrJSONDecoder(bytes.NewReader([]byte(`{ + "foo": { + "stuff": 1 + "otherStuff": 2 + } +} + `)), 100) + obj := generic{} + err := s.Decode(&obj) + if err == nil { + t.Fatal("expected error with json: prefix, got no error") + } + if !strings.HasPrefix(err.Error(), "json: line 3:") { + t.Fatalf("expected %q to have 'json: line 3:' prefix", err.Error()) + } +} + type generic map[string]interface{} func TestYAMLOrJSONDecoder(t *testing.T) {