...
1
2
3
4 package validation
5
6 import (
7 "k8s.io/apimachinery/pkg/api/meta"
8 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9 "k8s.io/apimachinery/pkg/util/validation/field"
10 "sigs.k8s.io/cli-utils/pkg/multierror"
11 "sigs.k8s.io/cli-utils/pkg/object"
12 )
13
14
15
16
17 type Validator struct {
18 Mapper meta.RESTMapper
19 Collector *Collector
20 }
21
22
23
24 func (v *Validator) Validate(objs []*unstructured.Unstructured) {
25 crds := findCRDs(objs)
26 for _, obj := range objs {
27 var objErrors []error
28 if err := v.validateKind(obj); err != nil {
29 objErrors = append(objErrors, err)
30 }
31 if err := v.validateName(obj); err != nil {
32 objErrors = append(objErrors, err)
33 }
34 if err := v.validateNamespace(obj, crds); err != nil {
35 objErrors = append(objErrors, err)
36 }
37 if len(objErrors) > 0 {
38
39 v.Collector.Collect(NewError(
40 multierror.Wrap(objErrors...),
41 object.UnstructuredToObjMetadata(obj),
42 ))
43 }
44 }
45 }
46
47
48
49 func findCRDs(us []*unstructured.Unstructured) []*unstructured.Unstructured {
50 var crds []*unstructured.Unstructured
51 for _, u := range us {
52 if object.IsCRD(u) {
53 crds = append(crds, u)
54 }
55 }
56 return crds
57 }
58
59
60 func (v *Validator) validateKind(u *unstructured.Unstructured) error {
61 if u.GetKind() == "" {
62 return field.Required(field.NewPath("kind"), "kind is required")
63 }
64 return nil
65 }
66
67
68 func (v *Validator) validateName(u *unstructured.Unstructured) error {
69 if u.GetName() == "" {
70 return field.Required(field.NewPath("metadata", "name"), "name is required")
71 }
72 return nil
73 }
74
75
76 func (v *Validator) validateNamespace(u *unstructured.Unstructured, crds []*unstructured.Unstructured) error {
77
78 if u.GetKind() == "" {
79 return nil
80 }
81 scope, err := object.LookupResourceScope(u, crds, v.Mapper)
82 if err != nil {
83 return err
84 }
85
86 ns := u.GetNamespace()
87 if scope == meta.RESTScopeNamespace && ns == "" {
88 return field.Required(field.NewPath("metadata", "namespace"), "namespace is required")
89 }
90 if scope == meta.RESTScopeRoot && ns != "" {
91 return field.Invalid(field.NewPath("metadata", "namespace"), ns, "namespace must be empty")
92 }
93 return nil
94 }
95
View as plain text