1
16
17
18
19 package replicaset
20
21 import (
22 "context"
23 "fmt"
24 "strconv"
25
26 extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
27 apiequality "k8s.io/apimachinery/pkg/api/equality"
28 apivalidation "k8s.io/apimachinery/pkg/api/validation"
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 "k8s.io/kubernetes/pkg/apis/apps"
43 appsvalidation "k8s.io/kubernetes/pkg/apis/apps/validation"
44 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
45 )
46
47
48 type rsStrategy struct {
49 runtime.ObjectTyper
50 names.NameGenerator
51 }
52
53
54 var Strategy = rsStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
55
56
57 var _ = rest.GarbageCollectionDeleteStrategy(Strategy)
58
59
60 func (rsStrategy) DefaultGarbageCollectionPolicy(ctx context.Context) rest.GarbageCollectionPolicy {
61 return rest.DeleteDependents
62 }
63
64
65 func (rsStrategy) NamespaceScoped() bool {
66 return true
67 }
68
69
70
71 func (rsStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
72 fields := map[fieldpath.APIVersion]*fieldpath.Set{
73 "apps/v1": fieldpath.NewSet(
74 fieldpath.MakePathOrDie("status"),
75 ),
76 }
77
78 return fields
79 }
80
81
82 func (rsStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
83 rs := obj.(*apps.ReplicaSet)
84 rs.Status = apps.ReplicaSetStatus{}
85
86 rs.Generation = 1
87
88 pod.DropDisabledTemplateFields(&rs.Spec.Template, nil)
89 }
90
91
92 func (rsStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
93 newRS := obj.(*apps.ReplicaSet)
94 oldRS := old.(*apps.ReplicaSet)
95
96 newRS.Status = oldRS.Status
97
98 pod.DropDisabledTemplateFields(&newRS.Spec.Template, &oldRS.Spec.Template)
99
100
101
102
103
104
105
106
107
108 if !apiequality.Semantic.DeepEqual(oldRS.Spec, newRS.Spec) {
109 newRS.Generation = oldRS.Generation + 1
110 }
111 }
112
113
114 func (rsStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
115 rs := obj.(*apps.ReplicaSet)
116 opts := pod.GetValidationOptionsFromPodTemplate(&rs.Spec.Template, nil)
117 return appsvalidation.ValidateReplicaSet(rs, opts)
118 }
119
120
121 func (rsStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
122 newRS := obj.(*apps.ReplicaSet)
123 var warnings []string
124 if msgs := utilvalidation.IsDNS1123Label(newRS.Name); len(msgs) != 0 {
125 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))
126 }
127 warnings = append(warnings, pod.GetWarningsForPodTemplate(ctx, field.NewPath("spec", "template"), &newRS.Spec.Template, nil)...)
128 return warnings
129 }
130
131
132 func (rsStrategy) Canonicalize(obj runtime.Object) {
133 }
134
135
136
137 func (rsStrategy) AllowCreateOnUpdate() bool {
138 return false
139 }
140
141
142 func (rsStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
143 newReplicaSet := obj.(*apps.ReplicaSet)
144 oldReplicaSet := old.(*apps.ReplicaSet)
145
146 opts := pod.GetValidationOptionsFromPodTemplate(&newReplicaSet.Spec.Template, &oldReplicaSet.Spec.Template)
147 allErrs := appsvalidation.ValidateReplicaSet(obj.(*apps.ReplicaSet), opts)
148 allErrs = append(allErrs, appsvalidation.ValidateReplicaSetUpdate(newReplicaSet, oldReplicaSet, opts)...)
149
150
151
152
153
154 if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
155 groupVersion := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
156 switch groupVersion {
157 case extensionsv1beta1.SchemeGroupVersion:
158
159 default:
160
161 allErrs = append(allErrs, apivalidation.ValidateImmutableField(newReplicaSet.Spec.Selector, oldReplicaSet.Spec.Selector, field.NewPath("spec").Child("selector"))...)
162 }
163 }
164
165 return allErrs
166 }
167
168
169 func (rsStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
170 var warnings []string
171 newReplicaSet := obj.(*apps.ReplicaSet)
172 oldReplicaSet := old.(*apps.ReplicaSet)
173 if newReplicaSet.Generation != oldReplicaSet.Generation {
174 warnings = pod.GetWarningsForPodTemplate(ctx, field.NewPath("spec", "template"), &newReplicaSet.Spec.Template, &oldReplicaSet.Spec.Template)
175 }
176 return warnings
177 }
178
179 func (rsStrategy) AllowUnconditionalUpdate() bool {
180 return true
181 }
182
183
184 func ToSelectableFields(rs *apps.ReplicaSet) fields.Set {
185 objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&rs.ObjectMeta, true)
186 rsSpecificFieldsSet := fields.Set{
187 "status.replicas": strconv.Itoa(int(rs.Status.Replicas)),
188 }
189 return generic.MergeFieldsSets(objectMetaFieldsSet, rsSpecificFieldsSet)
190 }
191
192
193 func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
194 rs, ok := obj.(*apps.ReplicaSet)
195 if !ok {
196 return nil, nil, fmt.Errorf("given object is not a ReplicaSet")
197 }
198 return labels.Set(rs.ObjectMeta.Labels), ToSelectableFields(rs), nil
199 }
200
201
202
203
204 func MatchReplicaSet(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
205 return apistorage.SelectionPredicate{
206 Label: label,
207 Field: field,
208 GetAttrs: GetAttrs,
209 }
210 }
211
212 type rsStatusStrategy struct {
213 rsStrategy
214 }
215
216
217 var StatusStrategy = rsStatusStrategy{Strategy}
218
219
220
221 func (rsStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
222 return map[fieldpath.APIVersion]*fieldpath.Set{
223 "apps/v1": fieldpath.NewSet(
224 fieldpath.MakePathOrDie("spec"),
225 ),
226 }
227 }
228
229 func (rsStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
230 newRS := obj.(*apps.ReplicaSet)
231 oldRS := old.(*apps.ReplicaSet)
232
233 newRS.Spec = oldRS.Spec
234 }
235
236 func (rsStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
237 return appsvalidation.ValidateReplicaSetStatusUpdate(obj.(*apps.ReplicaSet), old.(*apps.ReplicaSet))
238 }
239
240
241 func (rsStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
242 return nil
243 }
244
View as plain text