1
16
17
18
19 package replicationcontroller
20
21 import (
22 "context"
23 "fmt"
24 "strconv"
25 "strings"
26
27 corev1 "k8s.io/api/core/v1"
28 apiequality "k8s.io/apimachinery/pkg/api/equality"
29 "k8s.io/apimachinery/pkg/fields"
30 "k8s.io/apimachinery/pkg/labels"
31 "k8s.io/apimachinery/pkg/runtime"
32 "k8s.io/apimachinery/pkg/runtime/schema"
33 utilvalidation "k8s.io/apimachinery/pkg/util/validation"
34 "k8s.io/apimachinery/pkg/util/validation/field"
35 genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
36 "k8s.io/apiserver/pkg/registry/generic"
37 "k8s.io/apiserver/pkg/registry/rest"
38 apistorage "k8s.io/apiserver/pkg/storage"
39 "k8s.io/apiserver/pkg/storage/names"
40 "k8s.io/kubernetes/pkg/api/legacyscheme"
41 "k8s.io/kubernetes/pkg/api/pod"
42 api "k8s.io/kubernetes/pkg/apis/core"
43 "k8s.io/kubernetes/pkg/apis/core/helper"
44 corevalidation "k8s.io/kubernetes/pkg/apis/core/validation"
45 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
46 )
47
48
49 type rcStrategy struct {
50 runtime.ObjectTyper
51 names.NameGenerator
52 }
53
54
55 var Strategy = rcStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
56
57
58
59 func (rcStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy {
60 var groupVersion schema.GroupVersion
61 if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
62 groupVersion = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
63 }
64 switch groupVersion {
65 case corev1.SchemeGroupVersion:
66
67 return rest.OrphanDependents
68 default:
69 return rest.DeleteDependents
70 }
71 }
72
73
74 func (rcStrategy) NamespaceScoped() bool {
75 return true
76 }
77
78
79
80 func (rcStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
81 fields := map[fieldpath.APIVersion]*fieldpath.Set{
82 "v1": fieldpath.NewSet(
83 fieldpath.MakePathOrDie("status"),
84 ),
85 }
86
87 return fields
88 }
89
90
91 func (rcStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
92 controller := obj.(*api.ReplicationController)
93 controller.Status = api.ReplicationControllerStatus{}
94
95 controller.Generation = 1
96
97 pod.DropDisabledTemplateFields(controller.Spec.Template, nil)
98 }
99
100
101 func (rcStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
102 newController := obj.(*api.ReplicationController)
103 oldController := old.(*api.ReplicationController)
104
105 newController.Status = oldController.Status
106
107 pod.DropDisabledTemplateFields(newController.Spec.Template, oldController.Spec.Template)
108
109
110
111
112
113
114
115
116
117 if !apiequality.Semantic.DeepEqual(oldController.Spec, newController.Spec) {
118 newController.Generation = oldController.Generation + 1
119 }
120 }
121
122
123 func (rcStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
124 controller := obj.(*api.ReplicationController)
125 opts := pod.GetValidationOptionsFromPodTemplate(controller.Spec.Template, nil)
126 return corevalidation.ValidateReplicationController(controller, opts)
127 }
128
129
130 func (rcStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
131 newRC := obj.(*api.ReplicationController)
132 var warnings []string
133 if msgs := utilvalidation.IsDNS1123Label(newRC.Name); len(msgs) != 0 {
134 warnings = append(warnings, fmt.Sprintf("metadata.name: this is used in Pod names and hostnames, which can result in surprising behavior; a DNS label is recommended: %v", msgs))
135 }
136 warnings = append(warnings, pod.GetWarningsForPodTemplate(ctx, field.NewPath("spec", "template"), newRC.Spec.Template, nil)...)
137 return warnings
138 }
139
140
141 func (rcStrategy) Canonicalize(obj runtime.Object) {
142 }
143
144
145
146 func (rcStrategy) AllowCreateOnUpdate() bool {
147 return false
148 }
149
150
151 func (rcStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
152 oldRc := old.(*api.ReplicationController)
153 newRc := obj.(*api.ReplicationController)
154
155 opts := pod.GetValidationOptionsFromPodTemplate(newRc.Spec.Template, oldRc.Spec.Template)
156 validationErrorList := corevalidation.ValidateReplicationController(newRc, opts)
157 updateErrorList := corevalidation.ValidateReplicationControllerUpdate(newRc, oldRc, opts)
158 errs := append(validationErrorList, updateErrorList...)
159
160 for key, value := range helper.NonConvertibleFields(oldRc.Annotations) {
161 parts := strings.Split(key, "/")
162 if len(parts) != 2 {
163 continue
164 }
165 brokenField := parts[1]
166
167 switch {
168 case strings.Contains(brokenField, "selector"):
169 if !apiequality.Semantic.DeepEqual(oldRc.Spec.Selector, newRc.Spec.Selector) {
170 errs = append(errs, field.Invalid(field.NewPath("spec").Child("selector"), newRc.Spec.Selector, "cannot update non-convertible selector"))
171 }
172 default:
173 errs = append(errs, &field.Error{Type: field.ErrorTypeNotFound, BadValue: value, Field: brokenField, Detail: "unknown non-convertible field"})
174 }
175 }
176
177 return errs
178 }
179
180
181 func (rcStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
182 var warnings []string
183 oldRc := old.(*api.ReplicationController)
184 newRc := obj.(*api.ReplicationController)
185 if oldRc.Generation != newRc.Generation {
186 warnings = pod.GetWarningsForPodTemplate(ctx, field.NewPath("spec", "template"), oldRc.Spec.Template, newRc.Spec.Template)
187 }
188 return warnings
189 }
190
191 func (rcStrategy) AllowUnconditionalUpdate() bool {
192 return true
193 }
194
195
196 func ControllerToSelectableFields(controller *api.ReplicationController) fields.Set {
197 objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&controller.ObjectMeta, true)
198 controllerSpecificFieldsSet := fields.Set{
199 "status.replicas": strconv.Itoa(int(controller.Status.Replicas)),
200 }
201 return generic.MergeFieldsSets(objectMetaFieldsSet, controllerSpecificFieldsSet)
202 }
203
204
205 func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
206 rc, ok := obj.(*api.ReplicationController)
207 if !ok {
208 return nil, nil, fmt.Errorf("given object is not a replication controller")
209 }
210 return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), nil
211 }
212
213
214
215
216 func MatchController(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
217 return apistorage.SelectionPredicate{
218 Label: label,
219 Field: field,
220 GetAttrs: GetAttrs,
221 }
222 }
223
224 type rcStatusStrategy struct {
225 rcStrategy
226 }
227
228
229 var StatusStrategy = rcStatusStrategy{Strategy}
230
231
232
233 func (rcStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
234 return map[fieldpath.APIVersion]*fieldpath.Set{
235 "v1": fieldpath.NewSet(
236 fieldpath.MakePathOrDie("spec"),
237 ),
238 }
239 }
240
241 func (rcStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
242 newRc := obj.(*api.ReplicationController)
243 oldRc := old.(*api.ReplicationController)
244
245 newRc.Spec = oldRc.Spec
246 }
247
248 func (rcStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
249 return corevalidation.ValidateReplicationControllerStatusUpdate(obj.(*api.ReplicationController), old.(*api.ReplicationController))
250 }
251
252
253 func (rcStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
254 return nil
255 }
256
View as plain text