1
16
17 package namespace
18
19 import (
20 "context"
21 "fmt"
22
23 v1 "k8s.io/api/core/v1"
24 "k8s.io/apimachinery/pkg/fields"
25 "k8s.io/apimachinery/pkg/labels"
26 "k8s.io/apimachinery/pkg/runtime"
27 "k8s.io/apimachinery/pkg/util/validation/field"
28 "k8s.io/apiserver/pkg/registry/generic"
29 apistorage "k8s.io/apiserver/pkg/storage"
30 "k8s.io/apiserver/pkg/storage/names"
31 "k8s.io/kubernetes/pkg/api/legacyscheme"
32 api "k8s.io/kubernetes/pkg/apis/core"
33 "k8s.io/kubernetes/pkg/apis/core/validation"
34 "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
35 )
36
37
38 type namespaceStrategy struct {
39 runtime.ObjectTyper
40 names.NameGenerator
41 }
42
43
44
45 var Strategy = namespaceStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
46
47
48 func (namespaceStrategy) NamespaceScoped() bool {
49 return false
50 }
51
52
53
54 func (namespaceStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
55 return map[fieldpath.APIVersion]*fieldpath.Set{
56 "v1": fieldpath.NewSet(
57 fieldpath.MakePathOrDie("status"),
58 ),
59 }
60 }
61
62
63 func (namespaceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
64
65 namespace := obj.(*api.Namespace)
66 namespace.Status = api.NamespaceStatus{
67 Phase: api.NamespaceActive,
68 }
69
70
71 hasKubeFinalizer := false
72 for i := range namespace.Spec.Finalizers {
73 if namespace.Spec.Finalizers[i] == api.FinalizerKubernetes {
74 hasKubeFinalizer = true
75 break
76 }
77 }
78 if !hasKubeFinalizer {
79 if len(namespace.Spec.Finalizers) == 0 {
80 namespace.Spec.Finalizers = []api.FinalizerName{api.FinalizerKubernetes}
81 } else {
82 namespace.Spec.Finalizers = append(namespace.Spec.Finalizers, api.FinalizerKubernetes)
83 }
84 }
85 }
86
87
88 func (namespaceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
89 newNamespace := obj.(*api.Namespace)
90 oldNamespace := old.(*api.Namespace)
91 newNamespace.Spec.Finalizers = oldNamespace.Spec.Finalizers
92 newNamespace.Status = oldNamespace.Status
93 }
94
95
96 func (namespaceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
97 namespace := obj.(*api.Namespace)
98 return validation.ValidateNamespace(namespace)
99 }
100
101
102 func (namespaceStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
103 return nil
104 }
105
106
107 func (namespaceStrategy) Canonicalize(obj runtime.Object) {
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 ns := obj.(*api.Namespace)
126 if ns.Labels == nil {
127 ns.Labels = map[string]string{}
128 }
129 ns.Labels[v1.LabelMetadataName] = ns.Name
130 }
131
132
133 func (namespaceStrategy) AllowCreateOnUpdate() bool {
134 return false
135 }
136
137
138 func (namespaceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
139 errorList := validation.ValidateNamespace(obj.(*api.Namespace))
140 return append(errorList, validation.ValidateNamespaceUpdate(obj.(*api.Namespace), old.(*api.Namespace))...)
141 }
142
143
144 func (namespaceStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
145 return nil
146 }
147
148 func (namespaceStrategy) AllowUnconditionalUpdate() bool {
149 return true
150 }
151
152 type namespaceStatusStrategy struct {
153 namespaceStrategy
154 }
155
156 var StatusStrategy = namespaceStatusStrategy{Strategy}
157
158
159
160 func (namespaceStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
161 return map[fieldpath.APIVersion]*fieldpath.Set{
162 "v1": fieldpath.NewSet(
163 fieldpath.MakePathOrDie("spec"),
164 ),
165 }
166 }
167
168 func (namespaceStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
169 newNamespace := obj.(*api.Namespace)
170 oldNamespace := old.(*api.Namespace)
171 newNamespace.Spec = oldNamespace.Spec
172 }
173
174 func (namespaceStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
175 return validation.ValidateNamespaceStatusUpdate(obj.(*api.Namespace), old.(*api.Namespace))
176 }
177
178
179 func (namespaceStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
180 return nil
181 }
182
183 type namespaceFinalizeStrategy struct {
184 namespaceStrategy
185 }
186
187 var FinalizeStrategy = namespaceFinalizeStrategy{Strategy}
188
189 func (namespaceFinalizeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
190 return validation.ValidateNamespaceFinalizeUpdate(obj.(*api.Namespace), old.(*api.Namespace))
191 }
192
193
194 func (namespaceFinalizeStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
195 return nil
196 }
197
198
199
200 func (namespaceFinalizeStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
201 return map[fieldpath.APIVersion]*fieldpath.Set{
202 "v1": fieldpath.NewSet(
203 fieldpath.MakePathOrDie("status"),
204 ),
205 }
206 }
207
208
209 func (namespaceFinalizeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
210 newNamespace := obj.(*api.Namespace)
211 oldNamespace := old.(*api.Namespace)
212 newNamespace.Status = oldNamespace.Status
213 }
214
215
216 func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
217 namespaceObj, ok := obj.(*api.Namespace)
218 if !ok {
219 return nil, nil, fmt.Errorf("not a namespace")
220 }
221 return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil
222 }
223
224
225 func MatchNamespace(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
226 return apistorage.SelectionPredicate{
227 Label: label,
228 Field: field,
229 GetAttrs: GetAttrs,
230 }
231 }
232
233
234 func NamespaceToSelectableFields(namespace *api.Namespace) fields.Set {
235 objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&namespace.ObjectMeta, false)
236 specificFieldsSet := fields.Set{
237 "status.phase": string(namespace.Status.Phase),
238
239 "name": namespace.Name,
240 }
241 return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
242 }
243
View as plain text