1
2
3
4 package resid
5
6 import (
7 "strings"
8
9 "sigs.k8s.io/kustomize/kyaml/openapi"
10 "sigs.k8s.io/kustomize/kyaml/yaml"
11 )
12
13
14
15 type Gvk struct {
16 Group string `json:"group,omitempty" yaml:"group,omitempty"`
17 Version string `json:"version,omitempty" yaml:"version,omitempty"`
18 Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
19
20
21 isClusterScoped bool
22 }
23
24 func NewGvk(g, v, k string) Gvk {
25 result := Gvk{Group: g, Version: v, Kind: k}
26 result.isClusterScoped =
27 openapi.IsCertainlyClusterScoped(result.AsTypeMeta())
28 return result
29 }
30
31 func GvkFromNode(r *yaml.RNode) Gvk {
32 g, v := ParseGroupVersion(r.GetApiVersion())
33 return NewGvk(g, v, r.GetKind())
34 }
35
36
37 func FromKind(k string) Gvk {
38 return NewGvk("", "", k)
39 }
40
41
42 func ParseGroupVersion(apiVersion string) (group, version string) {
43 if i := strings.Index(apiVersion, "/"); i > -1 {
44 return apiVersion[:i], apiVersion[i+1:]
45 }
46 return "", apiVersion
47 }
48
49
50 func GvkFromString(s string) Gvk {
51 values := strings.Split(s, fieldSep)
52 if len(values) < 3 {
53
54 return Gvk{
55 Group: noGroup,
56 Version: noVersion,
57 Kind: noKind,
58 }
59 }
60 k := values[0]
61 if k == noKind {
62 k = ""
63 }
64 v := values[1]
65 if v == noVersion {
66 v = ""
67 }
68 g := strings.Join(values[2:], fieldSep)
69 if g == noGroup {
70 g = ""
71 }
72 return NewGvk(g, v, k)
73 }
74
75
76 const (
77 noGroup = "[noGrp]"
78 noVersion = "[noVer]"
79 noKind = "[noKind]"
80 fieldSep = "."
81 )
82
83
84 func (x Gvk) String() string {
85 g := x.Group
86 if g == "" {
87 g = noGroup
88 }
89 v := x.Version
90 if v == "" {
91 v = noVersion
92 }
93 k := x.Kind
94 if k == "" {
95 k = noKind
96 }
97 return strings.Join([]string{k, v, g}, fieldSep)
98 }
99
100
101
102 func (x Gvk) stableSortString() string {
103 stableNoGroup := "~G"
104 stableNoVersion := "~V"
105 stableNoKind := "~K"
106 stableFieldSeparator := "_"
107
108 g := x.Group
109 if g == "" {
110 g = stableNoGroup
111 }
112 v := x.Version
113 if v == "" {
114 v = stableNoVersion
115 }
116 k := x.Kind
117 if k == "" {
118 k = stableNoKind
119 }
120 return strings.Join([]string{g, v, k}, stableFieldSeparator)
121 }
122
123
124 func (x Gvk) ApiVersion() string {
125 if x.Group != "" {
126 return x.Group + "/" + x.Version
127 }
128 return x.Version
129 }
130
131
132
133
134 func (x Gvk) StringWoEmptyField() string {
135 var s []string
136 if x.Group != "" {
137 s = append(s, x.Group)
138 }
139 if x.Version != "" {
140 s = append(s, x.Version)
141 }
142 if x.Kind != "" {
143 s = append(s, x.Kind)
144 }
145 return strings.Join(s, "_")
146 }
147
148
149 func (x Gvk) Equals(o Gvk) bool {
150 return x.Group == o.Group && x.Version == o.Version && x.Kind == o.Kind
151 }
152
153
154
155
156
157 var orderFirst = []string{
158 "Namespace",
159 "ResourceQuota",
160 "StorageClass",
161 "CustomResourceDefinition",
162 "ServiceAccount",
163 "PodSecurityPolicy",
164 "Role",
165 "ClusterRole",
166 "RoleBinding",
167 "ClusterRoleBinding",
168 "ConfigMap",
169 "Secret",
170 "Endpoints",
171 "Service",
172 "LimitRange",
173 "PriorityClass",
174 "PersistentVolume",
175 "PersistentVolumeClaim",
176 "Deployment",
177 "StatefulSet",
178 "CronJob",
179 "PodDisruptionBudget",
180 }
181 var orderLast = []string{
182 "MutatingWebhookConfiguration",
183 "ValidatingWebhookConfiguration",
184 }
185 var typeOrders = func() map[string]int {
186 m := map[string]int{}
187 for i, n := range orderFirst {
188 m[n] = -len(orderFirst) + i
189 }
190 for i, n := range orderLast {
191 m[n] = 1 + i
192 }
193 return m
194 }()
195
196
197 func (x Gvk) IsLessThan(o Gvk) bool {
198 indexI := typeOrders[x.Kind]
199 indexJ := typeOrders[o.Kind]
200 if indexI != indexJ {
201 return indexI < indexJ
202 }
203 return x.stableSortString() < o.stableSortString()
204 }
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 func (x Gvk) IsSelected(selector *Gvk) bool {
222 if selector == nil {
223 return true
224 }
225 if len(selector.Group) > 0 {
226 if x.Group != selector.Group {
227 return false
228 }
229 }
230 if len(selector.Version) > 0 {
231 if x.Version != selector.Version {
232 return false
233 }
234 }
235 if len(selector.Kind) > 0 {
236 if x.Kind != selector.Kind {
237 return false
238 }
239 }
240 return true
241 }
242
243
244 func (x Gvk) AsTypeMeta() yaml.TypeMeta {
245 return yaml.TypeMeta{
246 APIVersion: x.ApiVersion(),
247 Kind: x.Kind,
248 }
249 }
250
251
252
253 func (x Gvk) IsClusterScoped() bool {
254 return x.isClusterScoped
255 }
256
View as plain text