2021-01-05 22:07:33 +00:00
|
|
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package ownerref
|
|
|
|
|
|
|
|
import (
|
2021-01-13 01:27:41 +00:00
|
|
|
"context"
|
2021-01-05 22:07:33 +00:00
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2021-01-05 22:07:33 +00:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
|
|
|
"go.pinniped.dev/internal/kubeclient"
|
|
|
|
)
|
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
func New(refObj kubeclient.Object) kubeclient.Middleware {
|
|
|
|
ref := metav1.OwnerReference{
|
|
|
|
Name: refObj.GetName(),
|
|
|
|
UID: refObj.GetUID(),
|
|
|
|
}
|
|
|
|
ref.APIVersion, ref.Kind = refObj.GetObjectKind().GroupVersionKind().ToAPIVersionAndKind()
|
|
|
|
refNamespace := refObj.GetNamespace()
|
|
|
|
|
|
|
|
// if refNamespace is empty, we assume the owner ref is to a cluster scoped object which can own any object
|
|
|
|
refIsNamespaced := len(refNamespace) != 0
|
|
|
|
|
|
|
|
// special handling of namespaces to treat them as namespace scoped to themselves
|
|
|
|
if isNamespace(refObj) {
|
|
|
|
refNamespace = refObj.GetName()
|
|
|
|
refIsNamespaced = true
|
|
|
|
}
|
2021-01-05 22:07:33 +00:00
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
return kubeclient.MiddlewareFunc(func(_ context.Context, rt kubeclient.RoundTrip) {
|
|
|
|
// we should not mess with owner refs on things we did not create
|
|
|
|
if rt.Verb() != kubeclient.VerbCreate {
|
|
|
|
return
|
|
|
|
}
|
2021-01-05 22:07:33 +00:00
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
// we probably do not want to set an owner ref on a subresource
|
|
|
|
if len(rt.Subresource()) != 0 {
|
|
|
|
return
|
|
|
|
}
|
2021-01-05 22:07:33 +00:00
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
// when ref is not cluster scoped, we ignore cluster scoped resources
|
|
|
|
if refIsNamespaced && !rt.NamespaceScoped() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// when ref is not cluster scoped, we require refNamespace to match
|
|
|
|
// the request namespace since cross namespace ownership is disallowed
|
|
|
|
if refIsNamespaced && refNamespace != rt.Namespace() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-02-05 01:02:59 +00:00
|
|
|
rt.MutateRequest(func(obj kubeclient.Object) error {
|
2021-01-13 01:27:41 +00:00
|
|
|
// we only want to set the owner ref on create and when one is not already present
|
|
|
|
if len(obj.GetOwnerReferences()) != 0 {
|
2021-02-05 01:02:59 +00:00
|
|
|
return nil
|
2021-01-13 01:27:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
obj.SetOwnerReferences([]metav1.OwnerReference{ref})
|
2021-02-05 01:02:59 +00:00
|
|
|
|
|
|
|
return nil
|
2021-01-13 01:27:41 +00:00
|
|
|
})
|
|
|
|
})
|
2021-01-05 22:07:33 +00:00
|
|
|
}
|
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
//nolint: gochecknoglobals
|
|
|
|
var namespaceGVK = corev1.SchemeGroupVersion.WithKind("Namespace")
|
2021-01-05 22:07:33 +00:00
|
|
|
|
2021-01-13 01:27:41 +00:00
|
|
|
func isNamespace(obj kubeclient.Object) bool {
|
|
|
|
_, ok := obj.(*corev1.Namespace)
|
|
|
|
return ok || obj.GetObjectKind().GroupVersionKind() == namespaceGVK
|
2021-01-05 22:07:33 +00:00
|
|
|
}
|