Skip to content

Commit

Permalink
WIP: Add a manifest annotation to be used for object deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
jottofar committed Apr 9, 2021
1 parent 07598f4 commit 37814ce
Show file tree
Hide file tree
Showing 12 changed files with 819 additions and 26 deletions.
133 changes: 107 additions & 26 deletions lib/resourcebuilder/resourcebuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
configclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
securityclientv1 "github.com/openshift/client-go/security/clientset/versioned/typed/security/v1"
"github.com/openshift/cluster-version-operator/lib/resourceapply"
"github.com/openshift/cluster-version-operator/lib/resourcedelete"
"github.com/openshift/cluster-version-operator/lib/resourceread"
"github.com/openshift/library-go/pkg/manifest"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -89,150 +90,230 @@ func (b *builder) Do(ctx context.Context) error {
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplySecurityContextConstraintsv1(ctx, b.securityClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteSecurityContextConstraintsv1(ctx, b.securityClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplySecurityContextConstraintsv1(ctx, b.securityClientv1, typedObject); err != nil {
return err
}
}
case *appsv1.DaemonSet:
if b.modifier != nil {
b.modifier(typedObject)
}
if err := b.modifyDaemonSet(ctx, typedObject); err != nil {
return err
}
if _, _, err := resourceapply.ApplyDaemonSetv1(ctx, b.appsClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteDaemonSetv1(ctx, b.appsClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if err := b.modifyDaemonSet(ctx, typedObject); err != nil {
return err
}
if _, _, err := resourceapply.ApplyDaemonSetv1(ctx, b.appsClientv1, typedObject); err != nil {
return err
}
}
return b.checkDaemonSetHealth(ctx, typedObject)
case *appsv1.Deployment:
if b.modifier != nil {
b.modifier(typedObject)
}
if err := b.modifyDeployment(ctx, typedObject); err != nil {
return err
}
if _, _, err := resourceapply.ApplyDeploymentv1(ctx, b.appsClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteDeploymentv1(ctx, b.appsClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if err := b.modifyDeployment(ctx, typedObject); err != nil {
return err
}
if _, _, err := resourceapply.ApplyDeploymentv1(ctx, b.appsClientv1, typedObject); err != nil {
return err
}
}
return b.checkDeploymentHealth(ctx, typedObject)
case *batchv1.Job:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyJobv1(ctx, b.batchClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteJobv1(ctx, b.batchClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyJobv1(ctx, b.batchClientv1, typedObject); err != nil {
return err
}
}
return b.checkJobHealth(ctx, typedObject)
case *corev1.ConfigMap:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyConfigMapv1(ctx, b.coreClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteConfigMapv1(ctx, b.coreClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyConfigMapv1(ctx, b.coreClientv1, typedObject); err != nil {
return err
}
}
case *corev1.Namespace:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyNamespacev1(ctx, b.coreClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteNamespacev1(ctx, b.coreClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyNamespacev1(ctx, b.coreClientv1, typedObject); err != nil {
return err
}
}
case *corev1.Service:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyServicev1(ctx, b.coreClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteServicev1(ctx, b.coreClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyServicev1(ctx, b.coreClientv1, typedObject); err != nil {
return err
}
}
case *corev1.ServiceAccount:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyServiceAccountv1(ctx, b.coreClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteServiceAccountv1(ctx, b.coreClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyServiceAccountv1(ctx, b.coreClientv1, typedObject); err != nil {
return err
}
}
case *rbacv1.ClusterRole:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyClusterRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteClusterRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyClusterRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
}
}
case *rbacv1.ClusterRoleBinding:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyClusterRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteClusterRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyClusterRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
}
}
case *rbacv1.Role:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyRolev1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
}
}
case *rbacv1.RoleBinding:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyRoleBindingv1(ctx, b.rbacClientv1, typedObject); err != nil {
return err
}
}
case *rbacv1beta1.ClusterRole:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyClusterRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteClusterRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyClusterRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
}
}
case *rbacv1beta1.ClusterRoleBinding:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyClusterRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteClusterRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyClusterRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
}
}
case *rbacv1beta1.Role:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyRolev1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
}
}
case *rbacv1beta1.RoleBinding:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyRoleBindingv1beta1(ctx, b.rbacClientv1beta1, typedObject); err != nil {
return err
}
}
case *apiextensionsv1.CustomResourceDefinition:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyCustomResourceDefinitionv1(ctx, b.apiextensionsClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteCustomResourceDefinitionv1(ctx, b.apiextensionsClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyCustomResourceDefinitionv1(ctx, b.apiextensionsClientv1, typedObject); err != nil {
return err
}
}
case *apiextensionsv1beta1.CustomResourceDefinition:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyCustomResourceDefinitionv1beta1(ctx, b.apiextensionsClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteCustomResourceDefinitionv1beta1(ctx, b.apiextensionsClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyCustomResourceDefinitionv1beta1(ctx, b.apiextensionsClientv1beta1, typedObject); err != nil {
return err
}
}
case *apiregistrationv1.APIService:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyAPIServicev1(ctx, b.apiregistrationClientv1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteAPIServicev1(ctx, b.apiregistrationClientv1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyAPIServicev1(ctx, b.apiregistrationClientv1, typedObject); err != nil {
return err
}
}
case *apiregistrationv1beta1.APIService:
if b.modifier != nil {
b.modifier(typedObject)
}
if _, _, err := resourceapply.ApplyAPIServicev1beta1(ctx, b.apiregistrationClientv1beta1, typedObject); err != nil {
if deleteIt, err := resourcedelete.DeleteAPIServicev1beta1(ctx, b.apiregistrationClientv1beta1, typedObject); err != nil {
return err
} else if !deleteIt {
if _, _, err := resourceapply.ApplyAPIServicev1beta1(ctx, b.apiregistrationClientv1beta1, typedObject); err != nil {
return err
}
}
default:
return fmt.Errorf("unrecognized manifest type: %T", obj)
Expand Down
63 changes: 63 additions & 0 deletions lib/resourcedelete/apiext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package resourcedelete

import (
"context"

apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextclientv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
apiextclientv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
)

func DeleteCustomResourceDefinitionv1beta1(ctx context.Context, client apiextclientv1beta1.CustomResourceDefinitionsGetter, required *apiextv1beta1.CustomResourceDefinition) (bool, error) {
if valid, err := validDeleteAnnotation(required.Annotations); !valid {
return valid, err
}
existing, err := client.CustomResourceDefinitions().Get(ctx, required.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
klog.V(4).Infof("Custom Resource Definition %s not found.", required.Name)
return false, nil
}
if err != nil {
return false, err
}
if deletionTime := existing.GetDeletionTimestamp(); deletionTime != nil {
klog.V(4).Infof("Custom Resource Definition %s is expected to be deleted by %s.", required.Name, deletionTime.String())
} else {
if err := client.CustomResourceDefinitions().Delete(ctx, required.Name, metav1.DeleteOptions{}); err != nil {
klog.V(4).Infof("Custom Resource Definition %s delete request failed, err=%v", required.Name, err)
return false, err
}
klog.V(4).Infof("Custom Resource Definition %s delete requested.", required.Name)
return true, nil
}
return false, nil
}

func DeleteCustomResourceDefinitionv1(ctx context.Context, client apiextclientv1.CustomResourceDefinitionsGetter, required *apiextv1.CustomResourceDefinition) (bool, error) {
if valid, err := validDeleteAnnotation(required.Annotations); !valid {
return valid, err
}
existing, err := client.CustomResourceDefinitions().Get(ctx, required.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
klog.V(4).Infof("Custom Resource Definition %s not found.", required.Name)
return false, nil
}
if err != nil {
return false, err
}
if deletionTime := existing.GetDeletionTimestamp(); deletionTime != nil {
klog.V(4).Infof("Custom Resource Definition %s is expected to be deleted by %s.", required.Name, deletionTime.String())
} else {
if err := client.CustomResourceDefinitions().Delete(ctx, required.Name, metav1.DeleteOptions{}); err != nil {
klog.V(4).Infof("Custom Resource Definition %s delete request failed, err=%v", required.Name, err)
return false, err
}
klog.V(4).Infof("Custom Resource Definition %s delete requested.", required.Name)
return true, nil
}
return false, nil
}
36 changes: 36 additions & 0 deletions lib/resourcedelete/apireg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package resourcedelete

import (
"context"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
apiregv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
apiregclientv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1"
)

func DeleteAPIServicev1(ctx context.Context, client apiregclientv1.APIServicesGetter, required *apiregv1.APIService) (bool, error) {
if valid, err := validDeleteAnnotation(required.Annotations); !valid {
return valid, err
}
existing, err := client.APIServices().Get(ctx, required.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
klog.V(4).Infof("API Service %s not found.", required.Name)
return false, nil
}
if err != nil {
return false, err
}
if deletionTime := existing.GetDeletionTimestamp(); deletionTime != nil {
klog.V(4).Infof("API Service %s is expected to be deleted by %s.", required.Name, deletionTime.String())
} else {
if err := client.APIServices().Delete(ctx, required.Name, metav1.DeleteOptions{}); err != nil {
klog.V(4).Infof("API Service %s delete request failed, err=%v", required.Name, err)
return false, err
}
klog.V(4).Infof("API Service %s delete requested.", required.Name)
return true, nil
}
return false, nil
}

0 comments on commit 37814ce

Please sign in to comment.