1 package kates
2
3 import (
4 "bufio"
5 "bytes"
6 "io"
7 "strings"
8
9 apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10 v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11 "k8s.io/apimachinery/pkg/runtime"
12 "k8s.io/apimachinery/pkg/runtime/schema"
13 utilyaml "k8s.io/apimachinery/pkg/util/yaml"
14 "k8s.io/client-go/kubernetes/scheme"
15 gw "sigs.k8s.io/gateway-api/apis/v1alpha1"
16 "sigs.k8s.io/yaml"
17
18 amb "github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v3alpha1"
19 )
20
21 var sch = runtime.NewScheme()
22
23 func init() {
24 if err := scheme.AddToScheme(sch); err != nil {
25 panic(err)
26 }
27 if err := apiextensions.AddToScheme(sch); err != nil {
28 panic(err)
29 }
30 if err := amb.AddToScheme(sch); err != nil {
31 panic(err)
32 }
33 if err := gw.AddToScheme(sch); err != nil {
34 panic(err)
35 }
36 }
37
38 func NewObject(kind, version string) (Object, error) {
39 return newFromGVK(schema.FromAPIVersionAndKind(version, kind))
40 }
41
42 func newFromGVK(gvk schema.GroupVersionKind) (Object, error) {
43 if sch.Recognizes(gvk) {
44 robj, err := sch.New(gvk)
45 if err != nil {
46 return nil, err
47 }
48 return robj.(Object), nil
49 } else {
50 un := &Unstructured{}
51 un.SetGroupVersionKind(gvk)
52 return un, nil
53 }
54 }
55
56
57
58
59 func NewObjectFromUnstructured(unstructured *Unstructured) (Object, error) {
60 if unstructured == nil {
61 return nil, nil
62 }
63
64 gvk := unstructured.GetObjectKind().GroupVersionKind()
65
66 obj, err := newFromGVK(gvk)
67 if err != nil {
68 return nil, err
69 }
70 err = convert(unstructured, &obj)
71 if err != nil {
72 return nil, err
73 }
74
75 return obj, nil
76 }
77
78 func NewUnstructured(kind, version string) *Unstructured {
79 uns := &Unstructured{}
80 uns.SetGroupVersionKind(schema.FromAPIVersionAndKind(version, kind))
81 return uns
82 }
83
84
85 func NewUnstructuredFromObject(obj Object) (result *Unstructured, err error) {
86 err = convert(obj, &result)
87 return
88 }
89
90 func parseManifests(text string, structured bool) ([]Object, error) {
91 yr := utilyaml.NewYAMLReader(bufio.NewReader(strings.NewReader(text)))
92
93 var result []Object
94
95 for {
96 bs, err := yr.Read()
97 if err == io.EOF {
98 break
99 }
100 if err != nil {
101 return nil, err
102 }
103
104 empty := true
105 for _, line := range bytes.Split(bs, []byte("\n")) {
106 if len(bytes.TrimSpace(bytes.SplitN(line, []byte("#"), 2)[0])) > 0 {
107 empty = false
108 break
109 }
110 }
111 if empty {
112 continue
113 }
114
115 var tm TypeMeta
116 err = yaml.Unmarshal(bs, &tm)
117 if err != nil {
118 return nil, err
119 }
120 var obj Object
121
122 if structured {
123 obj, err = newFromGVK(tm.GroupVersionKind())
124 if err != nil {
125 return nil, err
126 }
127 } else {
128 un := &Unstructured{}
129 un.SetGroupVersionKind(tm.GroupVersionKind())
130 obj = un
131 }
132
133 err = yaml.Unmarshal(bs, obj)
134 if err != nil {
135 return nil, err
136 }
137
138 result = append(result, obj)
139 }
140
141 return result, nil
142
143 }
144
145 func ParseManifestsToUnstructured(text string) ([]Object, error) {
146 return parseManifests(text, false)
147 }
148
149 func ParseManifests(text string) ([]Object, error) {
150 return parseManifests(text, true)
151 }
152
153 func HasOwnerReference(owner, other Object) bool {
154 refs := other.GetOwnerReferences()
155 for _, r := range refs {
156 if r.UID == owner.GetUID() {
157 return true
158 }
159 }
160 return false
161 }
162
163 func SetOwnerReferences(owner Object, objects ...Object) {
164 gvk := owner.GetObjectKind().GroupVersionKind()
165 for _, o := range objects {
166 if !HasOwnerReference(owner, o) {
167 ref := v1.NewControllerRef(owner, gvk)
168 o.SetOwnerReferences(append(o.GetOwnerReferences(), *ref))
169 }
170 }
171 }
172
173 func MergeUpdate(target *Unstructured, source *Unstructured) {
174 annotations := make(map[string]string)
175 for k, v := range target.GetAnnotations() {
176 annotations[k] = v
177 }
178 for k, v := range source.GetAnnotations() {
179 annotations[k] = v
180 }
181 target.SetAnnotations(annotations)
182
183 labels := make(map[string]string)
184 for k, v := range target.GetLabels() {
185 labels[k] = v
186 }
187 for k, v := range source.GetLabels() {
188 labels[k] = v
189 }
190 target.SetLabels(labels)
191
192 target.SetOwnerReferences(source.GetOwnerReferences())
193
194 spec, ok := source.Object["spec"]
195 if ok {
196 target.Object["spec"] = spec
197 } else {
198 delete(target.Object, "spec")
199 }
200 }
201
View as plain text