Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Harden yaml stream decoding in fluctl save
Browse files Browse the repository at this point in the history
Use go-yaml's Decoder instead of our own
  • Loading branch information
Alfonso Acosta committed Apr 13, 2019
1 parent f97508e commit cf189e2
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 47 deletions.
6 changes: 3 additions & 3 deletions cluster/kubernetes/resource/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ func ParseMultidoc(multidoc []byte, source string) (map[string]KubeManifest, err
var err error
for {
// In order to use the decoder to extract raw documents
// from the stream, we decode generically and encode again
// The result it the raw document (pretty-printed and
// without comments though)
// from the stream, we decode generically and encode again.
// The result is the raw document from the stream
// (pretty-printed and without comments)
var val interface{}
if err := decoder.Decode(&val); err != nil {
break
Expand Down
53 changes: 9 additions & 44 deletions cmd/fluxctl/save_cmd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"bufio"
"bytes"
"context"
"fmt"
Expand All @@ -11,7 +10,7 @@ import (

"github.com/pkg/errors"
"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
)

type saveOpts struct {
Expand Down Expand Up @@ -63,9 +62,6 @@ func (opts *saveOpts) RunE(cmd *cobra.Command, args []string) error {
return errors.Wrap(err, "exporting config")
}

yamls := bufio.NewScanner(bytes.NewReader(config))
yamls.Split(splitYAMLDocument)

if opts.path != "-" {
// check supplied path is a directory
if info, err := os.Stat(opts.path); err != nil {
Expand All @@ -75,11 +71,14 @@ func (opts *saveOpts) RunE(cmd *cobra.Command, args []string) error {
}
}

for yamls.Scan() {
decoder := yaml.NewDecoder(bytes.NewReader(config))

var decoderErr error
for {
var object saveObject
// Most unwanted fields are ignored at this point
if err := yaml.Unmarshal(yamls.Bytes(), &object); err != nil {
return errors.Wrap(err, "unmarshalling exported yaml")
if decoderErr = decoder.Decode(&object); decoderErr != nil {
break
}

// Filter out remaining unwanted keys from unstructured fields
Expand All @@ -91,8 +90,8 @@ func (opts *saveOpts) RunE(cmd *cobra.Command, args []string) error {
}
}

if yamls.Err() != nil {
return errors.Wrap(yamls.Err(), "splitting exported yaml")
if decoderErr != io.EOF {
return errors.Wrap(err, "unmarshalling exported yaml")
}

return nil
Expand Down Expand Up @@ -211,37 +210,3 @@ func abbreviateKind(kind string) string {
return kind
}
}

// Copied from k8s.io/client-go/1.5/pkg/util/yaml/decoder.go

const yamlSeparator = "\n---"

// splitYAMLDocument is a bufio.SplitFunc for splitting YAML streams into individual documents.
func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
sep := len([]byte(yamlSeparator))
if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 {
// We have a potential document terminator
i += sep
after := data[i:]
if len(after) == 0 {
// we can't read any more characters
if atEOF {
return len(data), data[:len(data)-sep], nil
}
return 0, nil, nil
}
if j := bytes.IndexByte(after, '\n'); j >= 0 {
return i + j + 1, data[0 : i-sep], nil
}
return 0, nil, nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), data, nil
}
// Request more data.
return 0, nil, nil
}

0 comments on commit cf189e2

Please sign in to comment.