|
1 | 1 | package internal |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "encoding/json" |
5 | 4 | "fmt" |
6 | 5 | "io" |
7 | 6 | "reflect" |
@@ -58,95 +57,6 @@ func checkFields(csv *operatorsv1alpha1.ClusterServiceVersion) (errs []errors.Er |
58 | 57 | return append(result.Errors, result.Warnings...) |
59 | 58 | } |
60 | 59 |
|
61 | | -// Recursive function that traverses a nested struct passed in as reflect value, and reports for errors/warnings |
62 | | -// in case of null struct field values. |
63 | | -func checkMissingFields(result *errors.ManifestResult, v reflect.Value, parentStructName string) { |
64 | | - if v.Kind() != reflect.Struct { |
65 | | - return |
66 | | - } |
67 | | - typ := v.Type() |
68 | | - |
69 | | - for i := 0; i < v.NumField(); i++ { |
70 | | - fieldValue := v.Field(i) |
71 | | - fieldType := typ.Field(i) |
72 | | - |
73 | | - tag := fieldType.Tag.Get("json") |
74 | | - // Ignore fields that are subsets of a primitive field. |
75 | | - if tag == "" { |
76 | | - continue |
77 | | - } |
78 | | - |
79 | | - // Omitted field tags will contain ",omitempty", and ignored tags will |
80 | | - // match "-" exactly, respectively. |
81 | | - isOptionalField := strings.Contains(tag, ",omitempty") || tag == "-" |
82 | | - emptyVal := isEmptyValue(fieldValue) |
83 | | - |
84 | | - newParentStructName := fieldType.Name |
85 | | - if parentStructName != "" { |
86 | | - newParentStructName = parentStructName + "." + newParentStructName |
87 | | - } |
88 | | - |
89 | | - switch fieldValue.Kind() { |
90 | | - case reflect.Struct: |
91 | | - updateLog(result, "struct", newParentStructName, emptyVal, isOptionalField) |
92 | | - if !emptyVal { |
93 | | - checkMissingFields(result, fieldValue, newParentStructName) |
94 | | - } |
95 | | - default: |
96 | | - updateLog(result, "field", newParentStructName, emptyVal, isOptionalField) |
97 | | - } |
98 | | - } |
99 | | -} |
100 | | - |
101 | | -// Returns updated error log with missing optional/mandatory field/struct objects. |
102 | | -func updateLog(result *errors.ManifestResult, typeName string, newParentStructName string, emptyVal bool, isOptionalField bool) { |
103 | | - if !emptyVal { |
104 | | - return |
105 | | - } |
106 | | - if isOptionalField { |
107 | | - // TODO: update the value field (typeName). |
108 | | - result.Add(errors.WarnFieldMissing("", newParentStructName, typeName)) |
109 | | - } else if newParentStructName != "Status" { |
110 | | - // TODO: update the value field (typeName). |
111 | | - result.Add(errors.ErrFieldMissing("", newParentStructName, typeName)) |
112 | | - } |
113 | | -} |
114 | | - |
115 | | -// Uses reflect package to check if the value of the object passed is null, returns a boolean accordingly. |
116 | | -// TODO: replace with reflect.Kind.IsZero() in go 1.13 |
117 | | -func isEmptyValue(v reflect.Value) bool { |
118 | | - switch v.Kind() { |
119 | | - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: |
120 | | - // Check if the value for 'Spec.InstallStrategy.StrategySpecRaw' field is present. This field is a RawMessage value type. Without a value, the key is explicitly set to 'null'. |
121 | | - if fieldValue, ok := v.Interface().(json.RawMessage); ok { |
122 | | - valString := string(fieldValue) |
123 | | - if valString == "null" { |
124 | | - return true |
125 | | - } |
126 | | - } |
127 | | - return v.Len() == 0 |
128 | | - // Currently the only CSV field with integer type is containerPort. Operator Verification Library raises a warning if containerPort field is missisng or if its value is 0. |
129 | | - // It is an optional field so the user can ignore the warning saying this field is missing if they intend to use port 0. |
130 | | - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
131 | | - return v.Int() == 0 |
132 | | - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: |
133 | | - return v.Uint() == 0 |
134 | | - case reflect.Float32, reflect.Float64: |
135 | | - return v.Float() == 0 |
136 | | - case reflect.Interface, reflect.Ptr: |
137 | | - return v.IsNil() |
138 | | - case reflect.Struct: |
139 | | - for i, n := 0, v.NumField(); i < n; i++ { |
140 | | - if !isEmptyValue(v.Field(i)) { |
141 | | - return false |
142 | | - } |
143 | | - } |
144 | | - return true |
145 | | - default: |
146 | | - panic(fmt.Sprintf("%v kind is not supported.", v.Kind())) |
147 | | - } |
148 | | -} |
149 | | - |
150 | 60 | // validateExamplesAnnotations compares alm/olm example annotations with provided APIs given |
151 | 61 | // by Spec.CustomResourceDefinitions.Owned and Spec.APIServiceDefinitions.Owned. |
152 | 62 | func validateExamplesAnnotations(csv *operatorsv1alpha1.ClusterServiceVersion) (errs []errors.Error) { |
|
0 commit comments