Skip to content

Commit 689a491

Browse files
committed
move checkMissingFields to its own file, as this is a general function
1 parent 0d05777 commit 689a491

File tree

2 files changed

+100
-90
lines changed

2 files changed

+100
-90
lines changed

pkg/validation/internal/csv.go

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package internal
22

33
import (
4-
"encoding/json"
54
"fmt"
65
"io"
76
"reflect"
@@ -58,95 +57,6 @@ func checkFields(csv *operatorsv1alpha1.ClusterServiceVersion) (errs []errors.Er
5857
return append(result.Errors, result.Warnings...)
5958
}
6059

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-
15060
// validateExamplesAnnotations compares alm/olm example annotations with provided APIs given
15161
// by Spec.CustomResourceDefinitions.Owned and Spec.APIServiceDefinitions.Owned.
15262
func validateExamplesAnnotations(csv *operatorsv1alpha1.ClusterServiceVersion) (errs []errors.Error) {
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package internal
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"reflect"
7+
"strings"
8+
9+
"github.com/operator-framework/api/pkg/validation/errors"
10+
)
11+
12+
// Recursive function that traverses a nested struct passed in as reflect
13+
// value, and reports for errors/warnings in case of nil struct field values.
14+
// TODO: make iterative
15+
func checkMissingFields(result *errors.ManifestResult, v reflect.Value, parentStructName string) {
16+
if v.Kind() != reflect.Struct {
17+
return
18+
}
19+
typ := v.Type()
20+
21+
for i := 0; i < v.NumField(); i++ {
22+
fieldValue := v.Field(i)
23+
fieldType := typ.Field(i)
24+
25+
tag := fieldType.Tag.Get("json")
26+
// Ignore fields that are subsets of a primitive field.
27+
if tag == "" {
28+
continue
29+
}
30+
31+
// Omitted field tags will contain ",omitempty", and ignored tags will
32+
// match "-" exactly, respectively.
33+
isOptionalField := strings.Contains(tag, ",omitempty") || tag == "-"
34+
emptyVal := isEmptyValue(fieldValue)
35+
36+
newParentStructName := fieldType.Name
37+
if parentStructName != "" {
38+
newParentStructName = parentStructName + "." + newParentStructName
39+
}
40+
41+
switch fieldValue.Kind() {
42+
case reflect.Struct:
43+
updateResult(result, "struct", newParentStructName, emptyVal, isOptionalField)
44+
if !emptyVal {
45+
checkMissingFields(result, fieldValue, newParentStructName)
46+
}
47+
default:
48+
updateResult(result, "field", newParentStructName, emptyVal, isOptionalField)
49+
}
50+
}
51+
}
52+
53+
// Returns updated ManifestResult with missing optional/mandatory field/struct objects.
54+
func updateResult(result *errors.ManifestResult, typeName string, newParentStructName string, emptyVal bool, isOptionalField bool) {
55+
if !emptyVal {
56+
return
57+
}
58+
if isOptionalField {
59+
// TODO: update the value field (typeName).
60+
result.Add(errors.WarnFieldMissing("", newParentStructName, typeName))
61+
} else if newParentStructName != "Status" {
62+
// TODO: update the value field (typeName).
63+
result.Add(errors.ErrFieldMissing("", newParentStructName, typeName))
64+
}
65+
}
66+
67+
// Uses reflect package to check if the value of the object passed is null, returns a boolean accordingly.
68+
// TODO: replace with reflect.Kind.IsZero() in go 1.13
69+
func isEmptyValue(v reflect.Value) bool {
70+
switch v.Kind() {
71+
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
72+
// 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'.
73+
if fieldValue, ok := v.Interface().(json.RawMessage); ok {
74+
valString := string(fieldValue)
75+
if valString == "null" {
76+
return true
77+
}
78+
}
79+
return v.Len() == 0
80+
// 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.
81+
// It is an optional field so the user can ignore the warning saying this field is missing if they intend to use port 0.
82+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
83+
return v.Int() == 0
84+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
85+
return v.Uint() == 0
86+
case reflect.Float32, reflect.Float64:
87+
return v.Float() == 0
88+
case reflect.Interface, reflect.Ptr:
89+
return v.IsNil()
90+
case reflect.Struct:
91+
for i, n := 0, v.NumField(); i < n; i++ {
92+
if !isEmptyValue(v.Field(i)) {
93+
return false
94+
}
95+
}
96+
return true
97+
default:
98+
panic(fmt.Sprintf("%v kind is not supported.", v.Kind()))
99+
}
100+
}

0 commit comments

Comments
 (0)