...
1
16
17 package customresource
18
19 import (
20 "context"
21 "fmt"
22
23 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
24
25 structurallisttype "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/listtype"
26 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/util/validation/field"
29 celconfig "k8s.io/apiserver/pkg/apis/cel"
30 )
31
32 type statusStrategy struct {
33 customResourceStrategy
34 }
35
36 func NewStatusStrategy(strategy customResourceStrategy) statusStrategy {
37 return statusStrategy{strategy}
38 }
39
40
41
42 func (a statusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
43 fields := map[fieldpath.APIVersion]*fieldpath.Set{
44 fieldpath.APIVersion(a.customResourceStrategy.kind.GroupVersion().String()): fieldpath.NewSet(
45
46
47
48
49
50
51
52
53 fieldpath.MakePathOrDie("spec"),
54 ),
55 }
56
57 return fields
58 }
59
60 func (a statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
61
62 newCustomResourceObject := obj.(*unstructured.Unstructured)
63 newCustomResource := newCustomResourceObject.UnstructuredContent()
64 status, ok := newCustomResource["status"]
65
66
67
68 managedFields := newCustomResourceObject.GetManagedFields()
69
70
71 oldCustomResourceObject := old.(*unstructured.Unstructured)
72
73
74 *newCustomResourceObject = *oldCustomResourceObject.DeepCopy()
75
76
77 newCustomResourceObject.SetManagedFields(managedFields)
78 newCustomResource = newCustomResourceObject.UnstructuredContent()
79 if ok {
80 newCustomResource["status"] = status
81 } else {
82 delete(newCustomResource, "status")
83 }
84 }
85
86
87 func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
88 uNew, ok := obj.(*unstructured.Unstructured)
89 if !ok {
90 return field.ErrorList{field.Invalid(field.NewPath(""), obj, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", obj))}
91 }
92 uOld, ok := old.(*unstructured.Unstructured)
93 if !ok {
94 return field.ErrorList{field.Invalid(field.NewPath(""), old, fmt.Sprintf("has type %T. Must be a pointer to an Unstructured type", old))}
95 }
96
97 var errs field.ErrorList
98 errs = append(errs, a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, uNew, uOld, a.scale)...)
99
100
101 if newErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uNew.Object); len(newErrs) > 0 {
102 if oldErrs := structurallisttype.ValidateListSetsAndMaps(nil, a.structuralSchema, uOld.Object); len(oldErrs) == 0 {
103 errs = append(errs, newErrs...)
104 }
105 }
106
107
108 if celValidator := a.customResourceStrategy.celValidator; celValidator != nil {
109 if has, err := hasBlockingErr(errs); has {
110 errs = append(errs, err)
111 } else {
112 err, _ := celValidator.Validate(ctx, nil, a.customResourceStrategy.structuralSchema, uNew.Object, uOld.Object, celconfig.RuntimeCELCostBudget)
113 errs = append(errs, err...)
114 }
115 }
116 return errs
117 }
118
119
120 func (statusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
121 return nil
122 }
123
View as plain text