1
2
3
4 package filters
5
6 import (
7 "fmt"
8 "sort"
9 "strings"
10
11 "sigs.k8s.io/kustomize/kyaml/kio"
12 "sigs.k8s.io/kustomize/kyaml/kio/kioutil"
13 "sigs.k8s.io/kustomize/kyaml/yaml"
14 )
15
16
17
18 var Filters = map[string]func() kio.Filter{
19 "FileSetter": func() kio.Filter { return &FileSetter{} },
20 "FormatFilter": func() kio.Filter { return &FormatFilter{} },
21 "GrepFilter": func() kio.Filter { return GrepFilter{} },
22 "MatchModifier": func() kio.Filter { return &MatchModifyFilter{} },
23 "Modifier": func() kio.Filter { return &Modifier{} },
24 }
25
26
27 type KFilter struct {
28 kio.Filter
29 }
30
31 func (t KFilter) MarshalYAML() (interface{}, error) {
32 return t.Filter, nil
33 }
34
35 func (t *KFilter) UnmarshalYAML(unmarshal func(interface{}) error) error {
36 i := map[string]interface{}{}
37 if err := unmarshal(i); err != nil {
38 return err
39 }
40 meta := &yaml.ResourceMeta{}
41 if err := unmarshal(meta); err != nil {
42 return err
43 }
44 filter, found := Filters[meta.Kind]
45 if !found {
46 var knownFilters []string
47 for k := range Filters {
48 knownFilters = append(knownFilters, k)
49 }
50 sort.Strings(knownFilters)
51 return fmt.Errorf("unsupported filter Kind %v: may be one of: [%s]",
52 meta, strings.Join(knownFilters, ","))
53 }
54 t.Filter = filter()
55
56 return unmarshal(t.Filter)
57 }
58
59
60
61 type Modifier struct {
62 Kind string `yaml:"kind,omitempty"`
63
64 Filters yaml.YFilters `yaml:"pipeline,omitempty"`
65 }
66
67 var _ kio.Filter = &Modifier{}
68
69 func (f Modifier) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
70 for i := range input {
71 if _, err := input[i].Pipe(f.Filters.Filters()...); err != nil {
72 return nil, err
73 }
74 }
75 return input, nil
76 }
77
78 type MatchModifyFilter struct {
79 Kind string `yaml:"kind,omitempty"`
80
81 MatchFilters []yaml.YFilters `yaml:"match,omitempty"`
82
83 ModifyFilters yaml.YFilters `yaml:"modify,omitempty"`
84 }
85
86 var _ kio.Filter = &MatchModifyFilter{}
87
88 func (f MatchModifyFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
89 var matches = input
90 var err error
91 for _, filter := range f.MatchFilters {
92 matches, err = MatchFilter{Filters: filter}.Filter(matches)
93 if err != nil {
94 return nil, err
95 }
96 }
97 _, err = Modifier{Filters: f.ModifyFilters}.Filter(matches)
98 if err != nil {
99 return nil, err
100 }
101 return input, nil
102 }
103
104 type MatchFilter struct {
105 Kind string `yaml:"kind,omitempty"`
106
107 Filters yaml.YFilters `yaml:"pipeline,omitempty"`
108 }
109
110 var _ kio.Filter = &MatchFilter{}
111
112 func (f MatchFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
113 var output []*yaml.RNode
114 for i := range input {
115 if v, err := input[i].Pipe(f.Filters.Filters()...); err != nil {
116 return nil, err
117 } else if v == nil {
118 continue
119 }
120 output = append(output, input[i])
121 }
122 return output, nil
123 }
124
125 type FilenameFmtVerb string
126
127 const (
128
129 KindFmt FilenameFmtVerb = "%k"
130
131
132 NameFmt FilenameFmtVerb = "%n"
133
134
135 NamespaceFmt FilenameFmtVerb = "%s"
136 )
137
138
139 type FileSetter struct {
140 Kind string `yaml:"kind,omitempty"`
141
142
143
144 FilenamePattern string `yaml:"filenamePattern,omitempty"`
145
146
147 Mode string `yaml:"mode,omitempty"`
148
149
150
151 Override bool `yaml:"override,omitempty"`
152 }
153
154 var _ kio.Filter = &FileSetter{}
155
156 const DefaultFilenamePattern = "%n_%k.yaml"
157
158 func (f *FileSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
159 if f.Mode == "" {
160 f.Mode = fmt.Sprintf("%d", 0600)
161 }
162 if f.FilenamePattern == "" {
163 f.FilenamePattern = DefaultFilenamePattern
164 }
165
166 resources := map[string][]*yaml.RNode{}
167 for i := range input {
168 if err := kioutil.CopyLegacyAnnotations(input[i]); err != nil {
169 return nil, err
170 }
171
172 m, err := input[i].GetMeta()
173 if err != nil {
174 return nil, err
175 }
176 file := f.FilenamePattern
177 file = strings.ReplaceAll(file, string(KindFmt), strings.ToLower(m.Kind))
178 file = strings.ReplaceAll(file, string(NameFmt), strings.ToLower(m.Name))
179 file = strings.ReplaceAll(file, string(NamespaceFmt), strings.ToLower(m.Namespace))
180
181 if _, found := m.Annotations[kioutil.PathAnnotation]; !found || f.Override {
182 if _, err := input[i].Pipe(yaml.SetAnnotation(kioutil.PathAnnotation, file)); err != nil {
183 return nil, err
184 }
185 if _, err := input[i].Pipe(yaml.SetAnnotation(kioutil.LegacyPathAnnotation, file)); err != nil {
186 return nil, err
187 }
188 }
189 resources[file] = append(resources[file], input[i])
190 }
191
192 var output []*yaml.RNode
193 for i := range resources {
194 if err := kioutil.SortNodes(resources[i]); err != nil {
195 return nil, err
196 }
197 for j := range resources[i] {
198 if _, err := resources[i][j].Pipe(
199 yaml.SetAnnotation(kioutil.IndexAnnotation, fmt.Sprintf("%d", j))); err != nil {
200 return nil, err
201 }
202 if _, err := resources[i][j].Pipe(
203 yaml.SetAnnotation(kioutil.LegacyIndexAnnotation, fmt.Sprintf("%d", j))); err != nil {
204 return nil, err
205 }
206 output = append(output, resources[i][j])
207 }
208 }
209 return output, nil
210 }
211
View as plain text