Using apimachinerymeta to manipulate finalizers to remove duplicate code

This commit is contained in:
nikhiljindal 2017-04-05 02:20:00 -07:00
parent bf532a30e3
commit df1288c3fa
11 changed files with 173 additions and 440 deletions

View File

@ -175,9 +175,7 @@ func NewConfigMapController(client federationclientset.Interface) *ConfigMapCont
})
configmapcontroller.deletionHelper = deletionhelper.NewDeletionHelper(
configmapcontroller.hasFinalizerFunc,
configmapcontroller.removeFinalizerFunc,
configmapcontroller.addFinalizerFunc,
configmapcontroller.updateConfigMap,
// objNameFunc
func(obj pkgruntime.Object) string {
configmap := obj.(*apiv1.ConfigMap)
@ -192,50 +190,11 @@ func NewConfigMapController(client federationclientset.Interface) *ConfigMapCont
return configmapcontroller
}
// hasFinalizerFunc returns true if the given object has the given finalizer in its ObjectMeta.
func (configmapcontroller *ConfigMapController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
// Sends the given updated object to apiserver.
// Assumes that the given object is a configmap.
func (configmapcontroller *ConfigMapController) updateConfigMap(obj pkgruntime.Object) (pkgruntime.Object, error) {
configmap := obj.(*apiv1.ConfigMap)
for i := range configmap.ObjectMeta.Finalizers {
if string(configmap.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// removeFinalizerFunc removes the given finalizers from the given objects ObjectMeta. Assumes that the given object is a configmap.
func (configmapcontroller *ConfigMapController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
configmap := obj.(*apiv1.ConfigMap)
newFinalizers := []string{}
hasFinalizer := false
for i := range configmap.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, configmap.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, configmap.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
configmap.ObjectMeta.Finalizers = newFinalizers
configmap, err := configmapcontroller.federatedApiClient.Core().ConfigMaps(configmap.Namespace).Update(configmap)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from configmap %s: %v", finalizers, configmap.Name, err)
}
return configmap, nil
}
// addFinalizerFunc adds the given finalizer to the given objects ObjectMeta. Assumes that the given object is a configmap.
func (configmapcontroller *ConfigMapController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
configmap := obj.(*apiv1.ConfigMap)
configmap.ObjectMeta.Finalizers = append(configmap.ObjectMeta.Finalizers, finalizers...)
configmap, err := configmapcontroller.federatedApiClient.Core().ConfigMaps(configmap.Namespace).Update(configmap)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to configmap %s: %v", finalizers, configmap.Name, err)
}
return configmap, nil
return configmapcontroller.federatedApiClient.Core().ConfigMaps(configmap.Namespace).Update(configmap)
}
func (configmapcontroller *ConfigMapController) Run(stopChan <-chan struct{}) {

View File

@ -193,9 +193,7 @@ func NewDaemonSetController(client federationclientset.Interface) *DaemonSetCont
})
daemonsetcontroller.deletionHelper = deletionhelper.NewDeletionHelper(
daemonsetcontroller.hasFinalizerFunc,
daemonsetcontroller.removeFinalizerFunc,
daemonsetcontroller.addFinalizerFunc,
daemonsetcontroller.updateDaemonSet,
// objNameFunc
func(obj pkgruntime.Object) string {
daemonset := obj.(*extensionsv1.DaemonSet)
@ -210,52 +208,11 @@ func NewDaemonSetController(client federationclientset.Interface) *DaemonSetCont
return daemonsetcontroller
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (daemonsetcontroller *DaemonSetController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
daemonset := obj.(*extensionsv1.DaemonSet)
for i := range daemonset.ObjectMeta.Finalizers {
if string(daemonset.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Sends the given updated object to apiserver.
// Assumes that the given object is a daemonset.
func (daemonsetcontroller *DaemonSetController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
func (daemonsetcontroller *DaemonSetController) updateDaemonSet(obj pkgruntime.Object) (pkgruntime.Object, error) {
daemonset := obj.(*extensionsv1.DaemonSet)
newFinalizers := []string{}
hasFinalizer := false
for i := range daemonset.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, daemonset.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, daemonset.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
daemonset.ObjectMeta.Finalizers = newFinalizers
daemonset, err := daemonsetcontroller.federatedApiClient.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from daemonset %s: %v", finalizers, daemonset.Name, err)
}
return daemonset, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a daemonset.
func (daemonsetcontroller *DaemonSetController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
daemonset := obj.(*extensionsv1.DaemonSet)
daemonset.ObjectMeta.Finalizers = append(daemonset.ObjectMeta.Finalizers, finalizers...)
daemonset, err := daemonsetcontroller.federatedApiClient.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to daemonset %s: %v", finalizers, daemonset.Name, err)
}
return daemonset, nil
return daemonsetcontroller.federatedApiClient.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}
func (daemonsetcontroller *DaemonSetController) Run(stopChan <-chan struct{}) {

View File

@ -207,9 +207,7 @@ func NewDeploymentController(federationClient fedclientset.Interface) *Deploymen
})
fdc.deletionHelper = deletionhelper.NewDeletionHelper(
fdc.hasFinalizerFunc,
fdc.removeFinalizerFunc,
fdc.addFinalizerFunc,
fdc.updateDeployment,
// objNameFunc
func(obj runtime.Object) string {
deployment := obj.(*extensionsv1.Deployment)
@ -224,52 +222,11 @@ func NewDeploymentController(federationClient fedclientset.Interface) *Deploymen
return fdc
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (fdc *DeploymentController) hasFinalizerFunc(obj runtime.Object, finalizer string) bool {
deployment := obj.(*extensionsv1.Deployment)
for i := range deployment.ObjectMeta.Finalizers {
if string(deployment.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Sends the given updated object to apiserver.
// Assumes that the given object is a deployment.
func (fdc *DeploymentController) removeFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
func (fdc *DeploymentController) updateDeployment(obj runtime.Object) (runtime.Object, error) {
deployment := obj.(*extensionsv1.Deployment)
newFinalizers := []string{}
hasFinalizer := false
for i := range deployment.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, deployment.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, deployment.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
deployment.ObjectMeta.Finalizers = newFinalizers
deployment, err := fdc.fedClient.Extensions().Deployments(deployment.Namespace).Update(deployment)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from deployment %s: %v", finalizers, deployment.Name, err)
}
return deployment, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a deployment.
func (fdc *DeploymentController) addFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
deployment := obj.(*extensionsv1.Deployment)
deployment.ObjectMeta.Finalizers = append(deployment.ObjectMeta.Finalizers, finalizers...)
deployment, err := fdc.fedClient.Extensions().Deployments(deployment.Namespace).Update(deployment)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to deployment %s: %v", finalizers, deployment.Name, err)
}
return deployment, nil
return fdc.fedClient.Extensions().Deployments(deployment.Namespace).Update(deployment)
}
func (fdc *DeploymentController) Run(workers int, stopCh <-chan struct{}) {

View File

@ -290,9 +290,7 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
})
ic.deletionHelper = deletionhelper.NewDeletionHelper(
ic.hasFinalizerFunc,
ic.removeFinalizerFunc,
ic.addFinalizerFunc,
ic.updateIngress,
// objNameFunc
func(obj pkgruntime.Object) string {
ingress := obj.(*extensionsv1beta1.Ingress)
@ -306,52 +304,11 @@ func NewIngressController(client federationclientset.Interface) *IngressControll
return ic
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (ic *IngressController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
// Sends the given updated object to apiserver.
// Assumes that the given object is an ingress.
func (ic *IngressController) updateIngress(obj pkgruntime.Object) (pkgruntime.Object, error) {
ingress := obj.(*extensionsv1beta1.Ingress)
for i := range ingress.ObjectMeta.Finalizers {
if string(ingress.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Assumes that the given object is a ingress.
func (ic *IngressController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
ingress := obj.(*extensionsv1beta1.Ingress)
newFinalizers := []string{}
hasFinalizer := false
for i := range ingress.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, ingress.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, ingress.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
ingress.ObjectMeta.Finalizers = newFinalizers
ingress, err := ic.federatedApiClient.Extensions().Ingresses(ingress.Namespace).Update(ingress)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from ingress %s: %v", finalizers, ingress.Name, err)
}
return ingress, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a ingress.
func (ic *IngressController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
ingress := obj.(*extensionsv1beta1.Ingress)
ingress.ObjectMeta.Finalizers = append(ingress.ObjectMeta.Finalizers, finalizers...)
ingress, err := ic.federatedApiClient.Extensions().Ingresses(ingress.Namespace).Update(ingress)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to ingress %s: %v", finalizers, ingress.Name, err)
}
return ingress, nil
return ic.federatedApiClient.Extensions().Ingresses(ingress.Namespace).Update(ingress)
}
func (ic *IngressController) Run(stopChan <-chan struct{}) {

View File

@ -179,9 +179,7 @@ func NewNamespaceController(client federationclientset.Interface, dynamicClientP
})
nc.deletionHelper = deletionhelper.NewDeletionHelper(
nc.hasFinalizerFunc,
nc.removeFinalizerFunc,
nc.addFinalizerFunc,
nc.updateNamespace,
// objNameFunc
func(obj runtime.Object) string {
namespace := obj.(*apiv1.Namespace)
@ -200,52 +198,11 @@ func NewNamespaceController(client federationclientset.Interface, dynamicClientP
return nc
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (nc *NamespaceController) hasFinalizerFunc(obj runtime.Object, finalizer string) bool {
namespace := obj.(*apiv1.Namespace)
for i := range namespace.ObjectMeta.Finalizers {
if string(namespace.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Sends the given update object to apiserver.
// Assumes that the given object is a namespace.
func (nc *NamespaceController) removeFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
func (nc *NamespaceController) updateNamespace(obj runtime.Object) (runtime.Object, error) {
namespace := obj.(*apiv1.Namespace)
newFinalizers := []string{}
hasFinalizer := false
for i := range namespace.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, namespace.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, namespace.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
namespace.ObjectMeta.Finalizers = newFinalizers
namespace, err := nc.federatedApiClient.Core().Namespaces().Update(namespace)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from namespace %s: %v", finalizers, namespace.Name, err)
}
return namespace, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a namespace.
func (nc *NamespaceController) addFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
namespace := obj.(*apiv1.Namespace)
namespace.ObjectMeta.Finalizers = append(namespace.ObjectMeta.Finalizers, finalizers...)
namespace, err := nc.federatedApiClient.Core().Namespaces().Finalize(namespace)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to namespace %s: %v", finalizers, namespace.Name, err)
}
return namespace, nil
return nc.federatedApiClient.Core().Namespaces().Update(namespace)
}
// Returns true if the given object has the given finalizer in its NamespaceSpec.

View File

@ -215,9 +215,7 @@ func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSe
})
frsc.deletionHelper = deletionhelper.NewDeletionHelper(
frsc.hasFinalizerFunc,
frsc.removeFinalizerFunc,
frsc.addFinalizerFunc,
frsc.updateReplicaSet,
// objNameFunc
func(obj runtime.Object) string {
replicaset := obj.(*extensionsv1.ReplicaSet)
@ -232,52 +230,11 @@ func NewReplicaSetController(federationClient fedclientset.Interface) *ReplicaSe
return frsc
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (frsc *ReplicaSetController) hasFinalizerFunc(obj runtime.Object, finalizer string) bool {
replicaset := obj.(*extensionsv1.ReplicaSet)
for i := range replicaset.ObjectMeta.Finalizers {
if string(replicaset.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Sends the given updated object to apiserver.
// Assumes that the given object is a replicaset.
func (frsc *ReplicaSetController) removeFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
func (frsc *ReplicaSetController) updateReplicaSet(obj runtime.Object) (runtime.Object, error) {
replicaset := obj.(*extensionsv1.ReplicaSet)
newFinalizers := []string{}
hasFinalizer := false
for i := range replicaset.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, replicaset.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, replicaset.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
replicaset.ObjectMeta.Finalizers = newFinalizers
replicaset, err := frsc.fedClient.Extensions().ReplicaSets(replicaset.Namespace).Update(replicaset)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from replicaset %s: %v", finalizers, replicaset.Name, err)
}
return replicaset, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a replicaset.
func (frsc *ReplicaSetController) addFinalizerFunc(obj runtime.Object, finalizers []string) (runtime.Object, error) {
replicaset := obj.(*extensionsv1.ReplicaSet)
replicaset.ObjectMeta.Finalizers = append(replicaset.ObjectMeta.Finalizers, finalizers...)
replicaset, err := frsc.fedClient.Extensions().ReplicaSets(replicaset.Namespace).Update(replicaset)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to replicaset %s: %v", finalizers, replicaset.Name, err)
}
return replicaset, nil
return frsc.fedClient.Extensions().ReplicaSets(replicaset.Namespace).Update(replicaset)
}
func (frsc *ReplicaSetController) Run(workers int, stopCh <-chan struct{}) {

View File

@ -295,9 +295,7 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
})
s.deletionHelper = deletionhelper.NewDeletionHelper(
s.hasFinalizerFunc,
s.removeFinalizerFunc,
s.addFinalizerFunc,
s.updateService,
// objNameFunc
func(obj pkgruntime.Object) string {
service := obj.(*v1.Service)
@ -316,52 +314,11 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
return s
}
// Returns true if the given object has the given finalizer in its ObjectMeta.
func (s *ServiceController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
service := obj.(*v1.Service)
for i := range service.ObjectMeta.Finalizers {
if string(service.ObjectMeta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizers from the given objects ObjectMeta.
// Sends the given updated object to apiserver.
// Assumes that the given object is a service.
func (s *ServiceController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
func (s *ServiceController) updateService(obj pkgruntime.Object) (pkgruntime.Object, error) {
service := obj.(*v1.Service)
newFinalizers := []string{}
hasFinalizer := false
for i := range service.ObjectMeta.Finalizers {
if !deletionhelper.ContainsString(finalizers, service.ObjectMeta.Finalizers[i]) {
newFinalizers = append(newFinalizers, service.ObjectMeta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
service.ObjectMeta.Finalizers = newFinalizers
service, err := s.federationClient.Core().Services(service.Namespace).Update(service)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from service %s: %v", finalizers, service.Name, err)
}
return service, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
// Assumes that the given object is a service.
func (s *ServiceController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
service := obj.(*v1.Service)
service.ObjectMeta.Finalizers = append(service.ObjectMeta.Finalizers, finalizers...)
service, err := s.federationClient.Core().Services(service.Namespace).Update(service)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to service %s: %v", finalizers, service.Name, err)
}
return service, nil
return s.federationClient.Core().Services(service.Namespace).Update(service)
}
// obj could be an *api.Service, or a DeletionFinalStateUnknown marker item.

View File

@ -183,9 +183,7 @@ func newFederationSyncController(client federationclientset.Interface, adapter f
})
s.deletionHelper = deletionhelper.NewDeletionHelper(
s.hasFinalizerFunc,
s.removeFinalizerFunc,
s.addFinalizerFunc,
s.updateObject,
// objNameFunc
func(obj pkgruntime.Object) string {
return adapter.ObjectMeta(obj).Name
@ -207,50 +205,9 @@ func (s *FederationSyncController) minimizeLatency() {
s.updateTimeout = 5 * time.Second
}
// hasFinalizerFunc returns true if the given object has the given finalizer in its ObjectMeta.
func (s *FederationSyncController) hasFinalizerFunc(obj pkgruntime.Object, finalizer string) bool {
meta := s.adapter.ObjectMeta(obj)
for i := range meta.Finalizers {
if string(meta.Finalizers[i]) == finalizer {
return true
}
}
return false
}
// Removes the finalizer from the given objects ObjectMeta.
func (s *FederationSyncController) removeFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
meta := s.adapter.ObjectMeta(obj)
newFinalizers := []string{}
hasFinalizer := false
for i := range meta.Finalizers {
if !deletionhelper.ContainsString(finalizers, meta.Finalizers[i]) {
newFinalizers = append(newFinalizers, meta.Finalizers[i])
} else {
hasFinalizer = true
}
}
if !hasFinalizer {
// Nothing to do.
return obj, nil
}
meta.Finalizers = newFinalizers
secret, err := s.adapter.FedUpdate(obj)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from %s %s: %v", finalizers, s.adapter.Kind(), meta.Name, err)
}
return secret, nil
}
// Adds the given finalizers to the given objects ObjectMeta.
func (s *FederationSyncController) addFinalizerFunc(obj pkgruntime.Object, finalizers []string) (pkgruntime.Object, error) {
meta := s.adapter.ObjectMeta(obj)
meta.Finalizers = append(meta.Finalizers, finalizers...)
secret, err := s.adapter.FedUpdate(obj)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to %s %s: %v", finalizers, s.adapter.Kind(), meta.Name, err)
}
return secret, nil
// Sends the given updated object to apiserver.
func (s *FederationSyncController) updateObject(obj pkgruntime.Object) (pkgruntime.Object, error) {
return s.adapter.FedUpdate(obj)
}
func (s *FederationSyncController) Run(stopChan <-chan struct{}) {

View File

@ -26,8 +26,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/tools/record"
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
finalizersutil "k8s.io/kubernetes/federation/pkg/federation-controller/util/finalizers"
"k8s.io/kubernetes/pkg/api"
"github.com/golang/glog"
@ -44,37 +46,29 @@ const (
FinalizerDeleteFromUnderlyingClusters string = "federation.kubernetes.io/delete-from-underlying-clusters"
)
type HasFinalizerFunc func(runtime.Object, string) bool
type RemoveFinalizerFunc func(runtime.Object, []string) (runtime.Object, error)
type AddFinalizerFunc func(runtime.Object, []string) (runtime.Object, error)
type UpdateObjFunc func(runtime.Object) (runtime.Object, error)
type ObjNameFunc func(runtime.Object) string
type DeletionHelper struct {
hasFinalizerFunc HasFinalizerFunc
removeFinalizerFunc RemoveFinalizerFunc
addFinalizerFunc AddFinalizerFunc
objNameFunc ObjNameFunc
updateTimeout time.Duration
eventRecorder record.EventRecorder
informer util.FederatedInformer
updater util.FederatedUpdater
updateObjFunc UpdateObjFunc
objNameFunc ObjNameFunc
updateTimeout time.Duration
eventRecorder record.EventRecorder
informer util.FederatedInformer
updater util.FederatedUpdater
}
func NewDeletionHelper(
hasFinalizerFunc HasFinalizerFunc, removeFinalizerFunc RemoveFinalizerFunc,
addFinalizerFunc AddFinalizerFunc, objNameFunc ObjNameFunc,
updateObjFunc UpdateObjFunc, objNameFunc ObjNameFunc,
updateTimeout time.Duration, eventRecorder record.EventRecorder,
informer util.FederatedInformer,
updater util.FederatedUpdater) *DeletionHelper {
informer util.FederatedInformer, updater util.FederatedUpdater) *DeletionHelper {
return &DeletionHelper{
hasFinalizerFunc: hasFinalizerFunc,
removeFinalizerFunc: removeFinalizerFunc,
addFinalizerFunc: addFinalizerFunc,
objNameFunc: objNameFunc,
updateTimeout: updateTimeout,
eventRecorder: eventRecorder,
informer: informer,
updater: updater,
updateObjFunc: updateObjFunc,
objNameFunc: objNameFunc,
updateTimeout: updateTimeout,
eventRecorder: eventRecorder,
informer: informer,
updater: updater,
}
}
@ -89,16 +83,24 @@ func NewDeletionHelper(
// This method should be called before creating objects in underlying clusters.
func (dh *DeletionHelper) EnsureFinalizers(obj runtime.Object) (
runtime.Object, error) {
finalizers := []string{}
if !dh.hasFinalizerFunc(obj, FinalizerDeleteFromUnderlyingClusters) {
finalizers = append(finalizers, FinalizerDeleteFromUnderlyingClusters)
finalizers := sets.String{}
hasFinalizer, err := finalizersutil.HasFinalizer(obj, FinalizerDeleteFromUnderlyingClusters)
if err != nil {
return obj, err
}
if !dh.hasFinalizerFunc(obj, metav1.FinalizerOrphanDependents) {
finalizers = append(finalizers, metav1.FinalizerOrphanDependents)
if !hasFinalizer {
finalizers.Insert(FinalizerDeleteFromUnderlyingClusters)
}
if len(finalizers) != 0 {
glog.V(2).Infof("Adding finalizers %v to %s", finalizers, dh.objNameFunc(obj))
return dh.addFinalizerFunc(obj, finalizers)
hasFinalizer, err = finalizersutil.HasFinalizer(obj, metav1.FinalizerOrphanDependents)
if err != nil {
return obj, err
}
if !hasFinalizer {
finalizers.Insert(metav1.FinalizerOrphanDependents)
}
if finalizers.Len() != 0 {
glog.V(2).Infof("Adding finalizers %v to %s", finalizers.List(), dh.objNameFunc(obj))
return dh.addFinalizers(obj, finalizers)
}
return obj, nil
}
@ -113,18 +115,25 @@ func (dh *DeletionHelper) HandleObjectInUnderlyingClusters(obj runtime.Object) (
runtime.Object, error) {
objName := dh.objNameFunc(obj)
glog.V(2).Infof("Handling deletion of federated dependents for object: %s", objName)
if !dh.hasFinalizerFunc(obj, FinalizerDeleteFromUnderlyingClusters) {
hasFinalizer, err := finalizersutil.HasFinalizer(obj, FinalizerDeleteFromUnderlyingClusters)
if err != nil {
return obj, err
}
if !hasFinalizer {
glog.V(2).Infof("obj does not have %s finalizer. Nothing to do", FinalizerDeleteFromUnderlyingClusters)
return obj, nil
}
hasOrphanFinalizer := dh.hasFinalizerFunc(obj, metav1.FinalizerOrphanDependents)
hasOrphanFinalizer, err := finalizersutil.HasFinalizer(obj, metav1.FinalizerOrphanDependents)
if err != nil {
return obj, err
}
if hasOrphanFinalizer {
glog.V(2).Infof("Found finalizer orphan. Nothing to do, just remove the finalizer")
// If the obj has FinalizerOrphan finalizer, then we need to orphan the
// corresponding objects in underlying clusters.
// Just remove both the finalizers in that case.
finalizers := []string{FinalizerDeleteFromUnderlyingClusters, metav1.FinalizerOrphanDependents}
return dh.removeFinalizerFunc(obj, finalizers)
finalizers := sets.NewString(FinalizerDeleteFromUnderlyingClusters, metav1.FinalizerOrphanDependents)
return dh.removeFinalizers(obj, finalizers)
}
glog.V(2).Infof("Deleting obj %s from underlying clusters", objName)
@ -180,5 +189,33 @@ func (dh *DeletionHelper) HandleObjectInUnderlyingClusters(obj runtime.Object) (
}
// All done. Just remove the finalizer.
return dh.removeFinalizerFunc(obj, []string{FinalizerDeleteFromUnderlyingClusters})
return dh.removeFinalizers(obj, sets.NewString(FinalizerDeleteFromUnderlyingClusters))
}
// Adds the given finalizers to the given objects ObjectMeta.
func (dh *DeletionHelper) addFinalizers(obj runtime.Object, finalizers sets.String) (runtime.Object, error) {
isUpdated, err := finalizersutil.AddFinalizers(obj, finalizers)
if err != nil || !isUpdated {
return obj, err
}
// Send the update to apiserver.
updatedObj, err := dh.updateObjFunc(obj)
if err != nil {
return nil, fmt.Errorf("failed to add finalizers %v to object %s: %v", finalizers, dh.objNameFunc(obj), err)
}
return updatedObj, nil
}
// Removes the given finalizers from the given objects ObjectMeta.
func (dh *DeletionHelper) removeFinalizers(obj runtime.Object, finalizers sets.String) (runtime.Object, error) {
isUpdated, err := finalizersutil.RemoveFinalizers(obj, finalizers)
if err != nil || !isUpdated {
return obj, err
}
// Send the update to apiserver.
updatedObj, err := dh.updateObjFunc(obj)
if err != nil {
return nil, fmt.Errorf("failed to remove finalizers %v from object %s: %v", finalizers, dh.objNameFunc(obj), err)
}
return updatedObj, nil
}

View File

@ -1,28 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package deletionhelper
// ContainsString returns true if the given string slice contains the given string.
// Returns false otherwise.
func ContainsString(arr []string, s string) bool {
for i := range arr {
if arr[i] == s {
return true
}
}
return false
}

View File

@ -0,0 +1,66 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Helper functions for manipulating finalizers.
package finalizers
import (
meta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
)
// HasFinalizer returns true if the given object has the given finalizer in its ObjectMeta.
func HasFinalizer(obj runtime.Object, finalizer string) (bool, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return false, err
}
finalizers := sets.NewString(accessor.GetFinalizers()...)
return finalizers.Has(finalizer), nil
}
// AddFinalizers adds the given finalizers to the given objects ObjectMeta.
// Returns true if the object was updated.
func AddFinalizers(obj runtime.Object, newFinalizers sets.String) (bool, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return false, err
}
oldFinalizers := sets.NewString(accessor.GetFinalizers()...)
if oldFinalizers.IsSuperset(newFinalizers) {
return false, nil
}
allFinalizers := oldFinalizers.Union(newFinalizers)
accessor.SetFinalizers(allFinalizers.List())
return true, nil
}
// RemoveFinalizers removes the given finalizers from the given objects ObjectMeta.
// Returns true if the object was updated.
func RemoveFinalizers(obj runtime.Object, finalizers sets.String) (bool, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return false, err
}
oldFinalizers := sets.NewString(accessor.GetFinalizers()...)
if oldFinalizers.Intersection(finalizers).Len() == 0 {
return false, nil
}
newFinalizers := oldFinalizers.Difference(finalizers)
accessor.SetFinalizers(newFinalizers.List())
return true, nil
}