1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package extension
17
18 import (
19 "fmt"
20 "strings"
21
22 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/constants"
23 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/util/pathslice"
24
25 "github.com/nasa9084/go-openapi"
26 )
27
28 var (
29 trimmableReferenceSuffixes = []string{"Name", "Id", "IdOrNum", "Email", "Link", "Reference"}
30 )
31
32
33 func IsReferenceField(schema *openapi.Schema) bool {
34 refSchema := schema
35 if schema.Type == "array" {
36 refSchema = schema.Items
37 }
38 _, ok := refSchema.Extension["x-dcl-references"]
39 return ok
40 }
41
42
43 func IsSensitiveField(schema *openapi.Schema) (bool, error) {
44 val, ok := schema.Extension["x-dcl-sensitive"]
45 if !ok {
46 return false, nil
47 }
48 if schema.Type != "string" {
49 return false, fmt.Errorf("only support sensitive fields of `string` type, but got type %v", schema.Type)
50 }
51 boolVal, ok := val.(bool)
52 if !ok {
53 return false, fmt.Errorf("wrong type for 'x-dcl-sensitive' extension: %T, expect to have bool", val)
54 }
55 return boolVal, nil
56 }
57
58 func HasSensitiveFields(schema *openapi.Schema) (bool, error) {
59 sensitive, err := IsSensitiveField(schema)
60 if err != nil {
61 return false, err
62 }
63 if sensitive {
64 return true, nil
65 }
66
67 switch schema.Type {
68 case "array":
69 return HasSensitiveFields(schema.Items)
70 case "object":
71 if schema.AdditionalProperties != nil {
72 return HasSensitiveFields(schema.AdditionalProperties)
73 }
74 for _, fieldSchema := range schema.Properties {
75 sensitive, err = HasSensitiveFields(fieldSchema)
76 if err != nil {
77 return false, err
78 }
79 if sensitive {
80 return true, nil
81 }
82 }
83 }
84
85 return false, nil
86 }
87
88 func HasIam(schema *openapi.Schema) (bool, error) {
89 val, ok := schema.Extension["x-dcl-has-iam"]
90 if !ok {
91 return false, nil
92 }
93 boolVal, ok := val.(bool)
94 if !ok {
95 return false, fmt.Errorf("wrong type for 'x-dcl-has-iam' extension: %T, expected to have bool", val)
96 }
97 return boolVal, nil
98 }
99
100 func IsImmutableField(schema *openapi.Schema) (bool, error) {
101 val, ok := schema.Extension["x-kubernetes-immutable"]
102 if !ok {
103 return false, nil
104 }
105 boolVal, ok := val.(bool)
106 if !ok {
107 return false, fmt.Errorf("wrong type for 'x-kubernetes-immutable' extension: %T, expect to have bool", val)
108 }
109 return boolVal, nil
110 }
111
112 func GetLabelsFieldSchema(schema *openapi.Schema) (labelsField string, fieldSchema *openapi.Schema, found bool, err error) {
113 raw, found := schema.Extension[constants.DCL_LABELS_FIELD]
114 if !found {
115 return "", nil, false, nil
116 }
117 labelsField, ok := raw.(string)
118 if !ok {
119 return "", nil, false, fmt.Errorf("wrong type for 'x-dcl-labels' extension: %T, expect to have string type", raw)
120 }
121 if labelsField == "" {
122 return "", nil, false, fmt.Errorf("'x-dcl-labels' field exists, but is an empty string")
123 }
124 path := strings.Split(labelsField, ".")
125 var ret *openapi.Schema
126 ret = schema
127 for _, field := range path {
128 if _, ok := ret.Properties[field]; !ok {
129 return "", nil, false, fmt.Errorf("couldn't find the schema for field %v", labelsField)
130 }
131 ret = ret.Properties[field]
132 }
133 return labelsField, ret, true, nil
134 }
135
136
137 func GetReferenceFieldName(path []string, schema *openapi.Schema) (string, error) {
138 field := pathslice.Base(path)
139 if len(path) == 1 && field == "parent" {
140 return "", fmt.Errorf("cannot get reference field name for 'parent' " +
141 "since 'parent' is typically split into multiple reference fields")
142 }
143
144 if schema.Type == "array" {
145 return field, nil
146 }
147 raw := schema.Extension["x-dcl-references"]
148 _, ok := raw.([]interface{})
149 if !ok {
150 return "", fmt.Errorf("wrong type for 'x-dcl-references' extension: %T, expect to have []interface{}", raw)
151 }
152 return formatReferenceFieldName(field), nil
153 }
154
155 func formatReferenceFieldName(fieldName string) string {
156
157
158 for _, suffix := range trimmableReferenceSuffixes {
159 if strings.HasSuffix(fieldName, suffix) {
160 return strings.TrimSuffix(fieldName, suffix) + "Ref"
161 }
162 }
163 return fieldName + "Ref"
164 }
165
166 func GetNameFieldSchema(schema *openapi.Schema) (*openapi.Schema, bool) {
167 s, ok := schema.Properties["name"]
168 if !ok {
169 return nil, false
170 }
171 return s, true
172 }
173
174 func IsResourceIDFieldServerGenerated(nameFieldSchema *openapi.Schema) (bool, error) {
175 val, ok := nameFieldSchema.Extension["x-dcl-server-generated-parameter"]
176 if !ok {
177 return false, nil
178 }
179 boolVal, ok := val.(bool)
180 if !ok {
181 return false, fmt.Errorf("wrong type for 'x-dcl-server-generated-parameter' extension: %T, expect to have bool", val)
182 }
183 return boolVal, nil
184 }
185
186 func GetNameValueTemplate(schema *openapi.Schema) (string, error) {
187 raw, ok := schema.Extension["x-dcl-id"]
188 if !ok {
189 return "", fmt.Errorf("'x-dcl-id' is not found")
190 }
191 template, ok := raw.(string)
192 if !ok {
193 return "", fmt.Errorf("wrong type for 'x-dcl-id' extension: %T, expect to have string type", raw)
194 }
195 return template, nil
196 }
197
198 func HasStateHint(schema *openapi.Schema) (bool, error) {
199 val, ok := schema.Extension["x-dcl-uses-state-hint"]
200 if !ok {
201 return false, nil
202 }
203
204 boolVal, ok := val.(bool)
205 if !ok {
206 return false, fmt.Errorf("wrong type for 'x-dcl-uses-state-hint' extension: %T, expect to have bool type", val)
207 }
208
209 return boolVal, nil
210 }
211
212 func IsMutableButUnreadableField(schema *openapi.Schema) (bool, error) {
213
214 val, ok := schema.Extension["x-dcl-mutable-unreadable"]
215 if !ok {
216 return false, nil
217 }
218
219 unreadable, ok := val.(bool)
220 if !ok {
221 return false, fmt.Errorf("wrong type for 'x-dcl-mutable-unreadable' extension: %T, expect to have bool type", val)
222 }
223
224 if !unreadable {
225 return false, nil
226 }
227
228
229 immutable, err := IsImmutableField(schema)
230 if err != nil {
231 return false, err
232 }
233 return !immutable, nil
234 }
235
View as plain text