mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Merge pull request #2480 from mortent/FormattingAnnotation
Add annotation for opting out of formatting
This commit is contained in:
@@ -31,6 +31,20 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"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.
|
// FormatInput returns the formatted input.
|
||||||
func FormatInput(input io.Reader) (*bytes.Buffer, error) {
|
func FormatInput(input io.Reader) (*bytes.Buffer, error) {
|
||||||
buff := &bytes.Buffer{}
|
buff := &bytes.Buffer{}
|
||||||
@@ -64,6 +78,15 @@ var _ kio.Filter = FormatFilter{}
|
|||||||
|
|
||||||
func (f FormatFilter) Filter(slice []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (f FormatFilter) Filter(slice []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
for i := range slice {
|
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"))
|
kindNode, err := slice[i].Pipe(yaml.Get("kind"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -94,6 +117,28 @@ func (f FormatFilter) Filter(slice []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
return slice, nil
|
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 {
|
type formatter struct {
|
||||||
apiVersion string
|
apiVersion string
|
||||||
kind string
|
kind string
|
||||||
|
|||||||
@@ -904,3 +904,118 @@ func TestFormatFileOrDirectory_trimWhiteSpace(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, string(testyaml.FormattedYaml1), string(b))
|
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)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
33
kyaml/testutil/testutil.go
Normal file
33
kyaml/testutil/testutil.go
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user