Merge pull request #2480 from mortent/FormattingAnnotation

Add annotation for opting out of formatting
This commit is contained in:
Kubernetes Prow Robot
2020-05-15 15:01:37 -07:00
committed by GitHub
3 changed files with 193 additions and 0 deletions

View File

@@ -31,6 +31,20 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml"
)
type FormattingStrategy = string
const (
// NoFmtAnnotation determines if the resource should be formatted.
FmtAnnotation string = "config.kubernetes.io/formatting"
// FmtStrategyStandard means the resource will be formatted according
// to the default rules.
FmtStrategyStandard FormattingStrategy = "standard"
// FmtStrategyNone means the resource will not be formatted.
FmtStrategyNone FormattingStrategy = "none"
)
// FormatInput returns the formatted input.
func FormatInput(input io.Reader) (*bytes.Buffer, error) {
buff := &bytes.Buffer{}
@@ -64,6 +78,15 @@ var _ kio.Filter = FormatFilter{}
func (f FormatFilter) Filter(slice []*yaml.RNode) ([]*yaml.RNode, error) {
for i := range slice {
fmtStrategy, err := getFormattingStrategy(slice[i])
if err != nil {
return nil, err
}
if fmtStrategy == FmtStrategyNone {
continue
}
kindNode, err := slice[i].Pipe(yaml.Get("kind"))
if err != nil {
return nil, err
@@ -94,6 +117,28 @@ func (f FormatFilter) Filter(slice []*yaml.RNode) ([]*yaml.RNode, error) {
return slice, nil
}
// getFormattingStrategy looks for the formatting annotation to determine
// which strategy should be used for formatting. The default is standard
// if no annotation is found.
func getFormattingStrategy(node *yaml.RNode) (FormattingStrategy, error) {
value, err := node.Pipe(yaml.GetAnnotation(FmtAnnotation))
if err != nil || value == nil {
return FmtStrategyStandard, err
}
fmtStrategy := value.YNode().Value
switch fmtStrategy {
case FmtStrategyStandard:
return FmtStrategyStandard, nil
case FmtStrategyNone:
return FmtStrategyNone, nil
default:
return "", fmt.Errorf(
"formatting annotation has illegal value %s", fmtStrategy)
}
}
type formatter struct {
apiVersion string
kind string

View File

@@ -904,3 +904,118 @@ func TestFormatFileOrDirectory_trimWhiteSpace(t *testing.T) {
assert.Equal(t, string(testyaml.FormattedYaml1), string(b))
}
func TestFormatFileOrDirectory_FmtAnnotation(t *testing.T) {
testCases := []struct {
name string
input []byte
expectedOutput []byte
expectError bool
}{
{
name: "no formatting annotation",
input: testyaml.UnformattedYaml1,
expectedOutput: testyaml.FormattedYaml1,
},
{
name: "formatting strategy none",
input: []byte(`
spec: a
status:
conditions:
- 3
- 1
- 2
apiVersion: example.com/v1beta1
kind: MyType
metadata:
annotations:
config.kubernetes.io/formatting: none
`),
expectedOutput: []byte(`
spec: a
status:
conditions:
- 3
- 1
- 2
apiVersion: example.com/v1beta1
kind: MyType
metadata:
annotations:
config.kubernetes.io/formatting: none
`),
},
{
name: "formatting strategy standard",
input: []byte(`
spec: a
status:
conditions:
- 3
- 1
- 2
apiVersion: example.com/v1beta1
kind: MyType
metadata:
annotations:
config.kubernetes.io/formatting: standard
`),
expectedOutput: []byte(`
apiVersion: example.com/v1beta1
kind: MyType
metadata:
annotations:
config.kubernetes.io/formatting: standard
spec: a
status:
conditions:
- 3
- 1
- 2
`),
},
{
name: "unknown formatting strategy",
input: []byte(`
spec: a
status:
conditions:
- 3
- 1
- 2
apiVersion: example.com/v1beta1
kind: MyType
metadata:
annotations:
config.kubernetes.io/formatting: unknown
`),
expectError: true,
},
}
for i := range testCases {
test := testCases[i]
t.Run(test.name, func(t *testing.T) {
f, err := ioutil.TempFile("", "yamlfmt*.yaml")
assert.NoError(t, err)
defer os.Remove(f.Name())
err = ioutil.WriteFile(f.Name(), test.input, 0600)
assert.NoError(t, err)
err = FormatFileOrDirectory(f.Name())
if test.expectError {
assert.Error(t, err)
return
}
assert.NoError(t, err)
b, err := ioutil.ReadFile(f.Name())
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(string(test.expectedOutput)),
strings.TrimSpace(string(b)))
})
}
}

View File

@@ -0,0 +1,33 @@
package testutil_test
import (
"bytes"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func UpdateYamlString(doc string, functions ...yaml.Filter) (string, error) {
b, err := UpdateYamlBytes([]byte(doc), functions...)
return string(b), err
}
func UpdateYamlBytes(b []byte, function ...yaml.Filter) ([]byte, error) {
var out bytes.Buffer
rw := kio.ByteReadWriter{
Reader: bytes.NewBuffer(b),
Writer: &out,
}
err := kio.Pipeline{
Inputs: []kio.Reader{&rw},
Filters: []kio.Filter{
kio.FilterAll(yaml.FilterFunc(
func(node *yaml.RNode) (*yaml.RNode, error) {
return node.Pipe(function...)
}),
),
},
Outputs: []kio.Writer{&rw},
}.Execute()
return out.Bytes(), err
}