1
2
3
4 package yaml
5
6 import (
7 "fmt"
8 "regexp"
9 "sort"
10 "strings"
11 )
12
13
14 var Filters = map[string]func() Filter{
15 "AnnotationClearer": func() Filter { return &AnnotationClearer{} },
16 "AnnotationGetter": func() Filter { return &AnnotationGetter{} },
17 "AnnotationSetter": func() Filter { return &AnnotationSetter{} },
18 "LabelSetter": func() Filter { return &LabelSetter{} },
19 "ElementAppender": func() Filter { return &ElementAppender{} },
20 "ElementMatcher": func() Filter { return &ElementMatcher{} },
21 "FieldClearer": func() Filter { return &FieldClearer{} },
22 "FilterMatcher": func() Filter { return &FilterMatcher{} },
23 "FieldMatcher": func() Filter { return &FieldMatcher{} },
24 "FieldSetter": func() Filter { return &FieldSetter{} },
25 "PathGetter": func() Filter { return &PathGetter{} },
26 "PathMatcher": func() Filter { return &PathMatcher{} },
27 "Parser": func() Filter { return &Parser{} },
28 "PrefixSetter": func() Filter { return &PrefixSetter{} },
29 "ValueReplacer": func() Filter { return &ValueReplacer{} },
30 "SuffixSetter": func() Filter { return &SuffixSetter{} },
31 "TeePiper": func() Filter { return &TeePiper{} },
32 }
33
34
35
36
37 type YFilter struct {
38 Filter
39 }
40
41 func (y YFilter) MarshalYAML() (interface{}, error) {
42 return y.Filter, nil
43 }
44
45 func (y *YFilter) UnmarshalYAML(unmarshal func(interface{}) error) error {
46 meta := &ResourceMeta{}
47 if err := unmarshal(meta); err != nil {
48 return err
49 }
50 filter, found := Filters[meta.Kind]
51 if !found {
52 var knownFilters []string
53 for k := range Filters {
54 knownFilters = append(knownFilters, k)
55 }
56 sort.Strings(knownFilters)
57 return fmt.Errorf("unsupported Filter Kind %s: may be one of: [%s]",
58 meta.Kind, strings.Join(knownFilters, ","))
59 }
60 y.Filter = filter()
61
62 if err := unmarshal(y.Filter); err != nil {
63 return err
64 }
65 return nil
66 }
67
68 type YFilters []YFilter
69
70 func (y YFilters) Filters() []Filter {
71 f := make([]Filter, 0, len(y))
72 for i := range y {
73 f = append(f, y[i].Filter)
74 }
75 return f
76 }
77
78 type FilterMatcher struct {
79 Kind string `yaml:"kind"`
80
81
82 Filters YFilters `yaml:"pipeline,omitempty"`
83 }
84
85 func (t FilterMatcher) Filter(rn *RNode) (*RNode, error) {
86 v, err := rn.Pipe(t.Filters.Filters()...)
87 if v == nil || err != nil {
88 return nil, err
89 }
90
91 return rn, err
92 }
93
94 type ValueReplacer struct {
95 Kind string `yaml:"kind"`
96
97 StringMatch string `yaml:"stringMatch"`
98 RegexMatch string `yaml:"regexMatch"`
99 Replace string `yaml:"replace"`
100 Count int `yaml:"count"`
101 }
102
103 func (s ValueReplacer) Filter(object *RNode) (*RNode, error) {
104 if s.Count == 0 {
105 s.Count = -1
106 }
107 switch {
108 case s.StringMatch != "":
109 object.value.Value = strings.Replace(object.value.Value, s.StringMatch, s.Replace, s.Count)
110 case s.RegexMatch != "":
111 r, err := regexp.Compile(s.RegexMatch)
112 if err != nil {
113 return nil, fmt.Errorf("ValueReplacer RegexMatch does not compile: %v", err)
114 }
115 object.value.Value = r.ReplaceAllString(object.value.Value, s.Replace)
116 default:
117 return nil, fmt.Errorf("ValueReplacer missing StringMatch and RegexMatch")
118 }
119 return object, nil
120 }
121
122 type PrefixSetter struct {
123 Kind string `yaml:"kind"`
124
125 Value string `yaml:"value"`
126 }
127
128 func (s PrefixSetter) Filter(object *RNode) (*RNode, error) {
129 if !strings.HasPrefix(object.value.Value, s.Value) {
130 object.value.Value = s.Value + object.value.Value
131 }
132 return object, nil
133 }
134
135 type SuffixSetter struct {
136 Kind string `yaml:"kind"`
137
138 Value string `yaml:"value"`
139 }
140
141 func (s SuffixSetter) Filter(object *RNode) (*RNode, error) {
142 if !strings.HasSuffix(object.value.Value, s.Value) {
143 object.value.Value += s.Value
144 }
145 return object, nil
146 }
147
View as plain text