Skip to content
This repository was archived by the owner on Apr 17, 2025. It is now read-only.

Commit 3d56dcf

Browse files
authored
Merge pull request #155 from erikgb/refactor/webhook-depy-deprecated
Remove last callers of webhooks.Deny function and delete it
2 parents a76c1c7 + 282ce63 commit 3d56dcf

File tree

2 files changed

+24
-55
lines changed

2 files changed

+24
-55
lines changed

internal/objects/validator.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ type request struct {
5454
obj *unstructured.Unstructured
5555
oldObj *unstructured.Unstructured
5656
op k8sadm.Operation
57+
gvr metav1.GroupVersionResource
58+
}
59+
60+
func (req request) gr() schema.GroupResource {
61+
return schema.GroupResource{Group: req.gvr.Group, Resource: req.gvr.Resource}
62+
}
63+
64+
func (req request) name() string {
65+
name := types.NamespacedName{Namespace: req.obj.GetNamespace(), Name: req.obj.GetName()}
66+
return name.String()
5767
}
5868

5969
func (v *Validator) Handle(ctx context.Context, req admission.Request) admission.Response {
@@ -137,9 +147,9 @@ func (v *Validator) handle(ctx context.Context, req *request) admission.Response
137147
}
138148

139149
if yes, dnses := v.hasConflict(inst); yes {
140-
dnsesStr := strings.Join(dnses, "\n * ")
141-
msg := fmt.Sprintf("\nCannot create %q (%s) in namespace %q because it would overwrite objects in the following descendant namespace(s):\n * %s\nTo fix this, choose a different name for the object, or remove the conflicting objects from the above namespaces.", inst.GetName(), inst.GroupVersionKind(), inst.GetNamespace(), dnsesStr)
142-
return webhooks.Deny(metav1.StatusReasonConflict, msg)
150+
dnsesStr := strings.Join(dnses, ",")
151+
err := fmt.Errorf("would overwrite objects in the following descendant namespace(s): %s. To fix this, choose a different name for the object, or remove the conflicting objects from the listed namespaces", dnsesStr)
152+
return webhooks.DenyConflict(req.gr(), req.name(), err)
143153
}
144154
return webhooks.Allow("source object")
145155
}
@@ -244,7 +254,8 @@ func (v *Validator) handleInherited(ctx context.Context, req *request, newSource
244254
// if this is an update, make sure that the canonical form of the object hasn't changed.
245255
switch op {
246256
case k8sadm.Create:
247-
return webhooks.Deny(metav1.StatusReasonForbidden, "Cannot create objects with the label \""+api.LabelInheritedFrom+"\"")
257+
err := fmt.Errorf("cannot create objects with the label \"%s\"", api.LabelInheritedFrom)
258+
return webhooks.DenyForbidden(req.gr(), req.name(), err)
248259

249260
case k8sadm.Delete:
250261
// There are few things more irritating in (K8s) life than having some stupid controller stop
@@ -256,7 +267,8 @@ func (v *Validator) handleInherited(ctx context.Context, req *request, newSource
256267
}
257268

258269
if !isDeleting {
259-
return webhooks.Deny(metav1.StatusReasonForbidden, "Cannot delete object propagated from namespace \""+oldSource+"\"")
270+
err := fmt.Errorf("cannot delete object propagated from namespace \"%s\"", oldSource)
271+
return webhooks.DenyForbidden(req.gr(), req.name(), err)
260272
}
261273

262274
return webhooks.Allow("allowing deletion of propagated object since namespace is being deleted")
@@ -266,21 +278,22 @@ func (v *Validator) handleInherited(ctx context.Context, req *request, newSource
266278
// added or deleted. Note that this label is *not* included in canonical(), below, so we
267279
// need to check it manually.
268280
if newSource != oldSource {
269-
return webhooks.Deny(metav1.StatusReasonForbidden, "Cannot modify the label \""+api.LabelInheritedFrom+"\"")
281+
err := fmt.Errorf("cannot modify the label \"%s\"", api.LabelInheritedFrom)
282+
return webhooks.DenyForbidden(req.gr(), req.name(), err)
270283
}
271284

272285
// If the existing object has an inheritedFrom label, it's a propagated object. Any user changes
273286
// should be rejected. Note that canonical does *not* compare any HNC labels or
274287
// annotations.
275288
if !reflect.DeepEqual(canonical(inst), canonical(oldInst)) {
276-
return webhooks.Deny(metav1.StatusReasonForbidden,
277-
"Cannot modify object propagated from namespace \""+oldSource+"\"")
289+
err := fmt.Errorf("cannot modify object propagated from namespace \"%s\"", oldSource)
290+
return webhooks.DenyForbidden(req.gr(), req.name(), err)
278291
}
279292

280293
// Check for all the labels and annotations (including HNC and non HNC)
281294
if !reflect.DeepEqual(oldInst.GetLabels(), inst.GetLabels()) || !reflect.DeepEqual(oldInst.GetAnnotations(), inst.GetAnnotations()) {
282-
return webhooks.Deny(metav1.StatusReasonForbidden,
283-
"Cannot modify object propagated from namespace \""+oldSource+"\"")
295+
err := fmt.Errorf("cannot modify object propagated from namespace \"%s\"", oldSource)
296+
return webhooks.DenyForbidden(req.gr(), req.name(), err)
284297
}
285298

286299
return webhooks.Allow("no illegal updates to propagated object")
@@ -365,6 +378,7 @@ func (v *Validator) decodeRequest(log logr.Logger, req admission.Request) (*requ
365378
obj: inst,
366379
oldObj: oldInst,
367380
op: req.Operation,
381+
gvr: req.Resource,
368382
}, nil
369383
}
370384

internal/webhooks/webhooks.go

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,6 @@ func DenyUnauthorized(reason string) admission.Response {
7474
return denyFromAPIError(apierrors.NewUnauthorized(reason))
7575
}
7676

77-
// Deny is a replacement for controller-runtime's admission.Denied() that allows you to set _both_ a
78-
// human-readable message _and_ a machine-readable reason, and also sets the code correctly instead
79-
// of hardcoding it to 403 Forbidden.
80-
//
81-
// NOTE: When manipulating the HNC configuration object via kubectl directly, kubectl
82-
// ignores the Message field and displays the Details field if an error is
83-
// StatusReasonInvalid.
84-
//
85-
// Deprecated: Use one of the explicit deny reason funcs instead; please don't add new callers.
86-
func Deny(reason metav1.StatusReason, msg string) admission.Response {
87-
err := &apierrors.StatusError{
88-
ErrStatus: metav1.Status{
89-
Code: CodeFromReason(reason),
90-
Message: msg,
91-
Reason: reason,
92-
},
93-
}
94-
return denyFromAPIError(err)
95-
}
96-
9777
// denyFromAPIError returns a response for denying a request with provided status error object.
9878
func denyFromAPIError(apiStatus apierrors.APIStatus) admission.Response {
9979
status := apiStatus.Status()
@@ -104,28 +84,3 @@ func denyFromAPIError(apiStatus apierrors.APIStatus) admission.Response {
10484
},
10585
}
10686
}
107-
108-
// CodeFromReason implements the needed subset of
109-
// https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#StatusReason
110-
func CodeFromReason(reason metav1.StatusReason) int32 {
111-
switch reason {
112-
case metav1.StatusReasonUnknown:
113-
return 500
114-
case metav1.StatusReasonUnauthorized:
115-
return 401
116-
case metav1.StatusReasonForbidden:
117-
return 403
118-
case metav1.StatusReasonConflict:
119-
return 409
120-
case metav1.StatusReasonBadRequest:
121-
return 400
122-
case metav1.StatusReasonInvalid:
123-
return 422
124-
case metav1.StatusReasonInternalError:
125-
return 500
126-
case metav1.StatusReasonServiceUnavailable:
127-
return 503
128-
default:
129-
return 500
130-
}
131-
}

0 commit comments

Comments
 (0)