Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make seq indent configurable and add retain seq indent functionality #4043

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions kyaml/kio/byteio_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type ByteReadWriter struct {
// the Resources, otherwise they will be cleared.
KeepReaderAnnotations bool

// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
PreserveSeqIndent bool

// Style is a style that is set on the Resource Node Document.
Style yaml.Style

Expand All @@ -53,6 +56,7 @@ func (rw *ByteReadWriter) Read() ([]*yaml.RNode, error) {
b := &ByteReader{
Reader: rw.Reader,
OmitReaderAnnotations: rw.OmitReaderAnnotations,
PreserveSeqIndent: rw.PreserveSeqIndent,
}
val, err := b.Read()
if rw.FunctionConfig == nil {
Expand Down Expand Up @@ -109,9 +113,12 @@ type ByteReader struct {
Reader io.Reader

// OmitReaderAnnotations will configures Read to skip setting the config.kubernetes.io/index
// annotation on Resources as they are Read.
// and internal.config.kubernetes.io/seqindent annotations on Resources as they are Read.
OmitReaderAnnotations bool

// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
PreserveSeqIndent bool

// SetAnnotations is a map of caller specified annotations to set on resources as they are read
// These are independent of the annotations controlled by OmitReaderAnnotations
SetAnnotations map[string]string
Expand Down Expand Up @@ -166,6 +173,10 @@ func splitDocuments(s string) ([]string, error) {
}

func (r *ByteReader) Read() ([]*yaml.RNode, error) {
if r.PreserveSeqIndent && r.OmitReaderAnnotations {
return nil, errors.Errorf(`"PreserveSeqIndent" option adds a reader annotation, please set "OmitReaderAnnotations" to false`)
}

output := ResourceNodeSlice{}

// by manually splitting resources -- otherwise the decoder will get the Resource
Expand All @@ -191,10 +202,11 @@ func (r *ByteReader) Read() ([]*yaml.RNode, error) {
values[i] += "\n"
}
decoder := yaml.NewDecoder(bytes.NewBufferString(values[i]))
node, err := r.decode(index, decoder)
node, err := r.decode(values[i], index, decoder)
if err == io.EOF {
continue
}

if err != nil {
return nil, errors.Wrap(err)
}
Expand Down Expand Up @@ -245,7 +257,7 @@ func (r *ByteReader) Read() ([]*yaml.RNode, error) {
return output, nil
}

func (r *ByteReader) decode(index int, decoder *yaml.Decoder) (*yaml.RNode, error) {
func (r *ByteReader) decode(originalYAML string, index int, decoder *yaml.Decoder) (*yaml.RNode, error) {
node := &yaml.Node{}
err := decoder.Decode(node)
if err == io.EOF {
Expand All @@ -268,6 +280,14 @@ func (r *ByteReader) decode(index int, decoder *yaml.Decoder) (*yaml.RNode, erro
}
if !r.OmitReaderAnnotations {
r.SetAnnotations[kioutil.IndexAnnotation] = fmt.Sprintf("%d", index)

if r.PreserveSeqIndent {
// derive and add the seqindent annotation
seqIndentStyle := yaml.DeriveSeqIndentStyle(originalYAML)
if seqIndentStyle != "" {
r.SetAnnotations[kioutil.SeqIndentAnnotation] = fmt.Sprintf("%s", seqIndentStyle)
}
}
}
var keys []string
for k := range r.SetAnnotations {
Expand Down
100 changes: 100 additions & 0 deletions kyaml/kio/byteio_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/stretchr/testify/assert"
. "sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
)

func TestByteReader(t *testing.T) {
Expand Down Expand Up @@ -805,3 +806,102 @@ items:
})
}
}

// TestByteReader_AddSeqIndentAnnotation tests if the internal.config.kubernetes.io/seqindent
// annotation is added to resources appropriately
func TestByteReader_AddSeqIndentAnnotation(t *testing.T) {
type testCase struct {
name string
err string
input string
expectedAnnoValue string
OmitReaderAnnotations bool
}

testCases := []testCase{
{
name: "read with wide indentation",
input: `apiVersion: apps/v1
kind: Deployment
spec:
- foo
- bar
- baz
`,
expectedAnnoValue: "wide",
},
{
name: "read with compact indentation",
input: `apiVersion: apps/v1
kind: Deployment
spec:
- foo
- bar
- baz
`,
expectedAnnoValue: "compact",
},
{
name: "read with mixed indentation, wide wins",
input: `apiVersion: apps/v1
kind: Deployment
spec:
- foo
- bar
- baz
env:
- foo
- bar
`,
expectedAnnoValue: "wide",
},
{
name: "read with mixed indentation, compact wins",
input: `apiVersion: apps/v1
kind: Deployment
spec:
- foo
- bar
- baz
env:
- foo
- bar
`,
expectedAnnoValue: "compact",
},
{
name: "error if conflicting options",
input: `apiVersion: apps/v1
kind: Deployment
spec:
- foo
- bar
- baz
env:
- foo
- bar
`,
OmitReaderAnnotations: true,
err: `"PreserveSeqIndent" option adds a reader annotation, please set "OmitReaderAnnotations" to false`,
},
}

for i := range testCases {
tc := testCases[i]
t.Run(tc.name, func(t *testing.T) {
rNodes, err := (&ByteReader{
OmitReaderAnnotations: tc.OmitReaderAnnotations,
PreserveSeqIndent: true,
Reader: bytes.NewBuffer([]byte(tc.input)),
}).Read()
if tc.err != "" {
assert.Error(t, err)
assert.Equal(t, tc.err, err.Error())
return
}
assert.NoError(t, err)
actual := rNodes[0].GetAnnotations()[kioutil.SeqIndentAnnotation]
assert.Equal(t, tc.expectedAnnoValue, actual)
})
}
}
Loading