kubeconform/pkg/resource/stream.go
2020-11-15 17:05:11 +01:00

68 lines
1.6 KiB
Go

package resource
import (
"bufio"
"bytes"
"context"
"io"
)
// Thank you https://github.com/helm/helm-classic/blob/master/codec/yaml.go#L90
func SplitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
const yamlSeparator = "\n---"
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
}
// FromStream reads resources from a byte stream, usually here stdin
func FromStream(ctx context.Context, path string, r io.Reader) (<-chan Resource, <-chan error) {
resources := make(chan Resource)
errors := make(chan error)
go func() {
scanner := bufio.NewScanner(r)
const maxResourceSize = 4 * 1024 * 1024 // 4MB ought to be enough for everybody
buf := make([]byte, maxResourceSize)
scanner.Buffer(buf, maxResourceSize)
scanner.Split(SplitYAMLDocument)
SCAN:
for res := scanner.Scan(); res != false; res = scanner.Scan() {
select {
case <-ctx.Done():
break SCAN
default:
}
resources <- Resource{Path: path, Bytes: scanner.Bytes()}
}
close(resources)
close(errors)
}()
return resources, errors
}