Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,23 @@ rules:
- pods/status
verbs:
- get
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- policy
resources:
- poddisruptionbudgets/finalizers
verbs:
- update
- apiGroups:
- ""
resources:
Expand Down
4 changes: 4 additions & 0 deletions controllers/apps/cluster_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -41,6 +42,7 @@ import (
appsv1beta1 "github.com/apecloud/kubeblocks/apis/apps/v1beta1"
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
extensionsv1alpha1 "github.com/apecloud/kubeblocks/apis/extensions/v1alpha1"
"github.com/apecloud/kubeblocks/apis/workloads/legacy"
workloadsv1alpha1 "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1"
"github.com/apecloud/kubeblocks/pkg/constant"
"github.com/apecloud/kubeblocks/pkg/controller/graph"
Expand Down Expand Up @@ -121,6 +123,8 @@ func init() {
model.AddScheme(extensionsv1alpha1.AddToScheme)
model.AddScheme(workloadsv1alpha1.AddToScheme)
model.AddScheme(appsv1beta1.AddToScheme)
model.AddScheme(apiextv1.AddToScheme)
model.AddScheme(legacy.AddToScheme)
}

// PlanBuilder implementation
Expand Down
5 changes: 4 additions & 1 deletion controllers/apps/component_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ type ComponentReconciler struct {
// +kubebuilder:rbac:groups=core,resources=pods/finalizers,verbs=update
// +kubebuilder:rbac:groups=core,resources=pods/exec,verbs=create

// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;update;patch;delete
// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets/finalizers,verbs=update

// read only + watch access
// +kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch

Expand Down Expand Up @@ -148,7 +151,7 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// handle finalizers and referenced definition labels
&componentMetaTransformer{},
// validate referenced componentDefinition objects, and build synthesized component
&componentLoadResourcesTransformer{},
&componentLoadResourcesTransformer{Client: r.Client},
// do validation for the spec & definition consistency
&componentValidationTransformer{},
// handle sidecar container
Expand Down
4 changes: 4 additions & 0 deletions controllers/apps/transform_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package apps
import (
snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
batchv1 "k8s.io/api/batch/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand All @@ -32,6 +33,7 @@ import (
appsv1beta1 "github.com/apecloud/kubeblocks/apis/apps/v1beta1"
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
extensionsv1alpha1 "github.com/apecloud/kubeblocks/apis/extensions/v1alpha1"
"github.com/apecloud/kubeblocks/apis/workloads/legacy"
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1"
)

Expand All @@ -48,7 +50,9 @@ func init() {
utilruntime.Must(snapshotv1.AddToScheme(rscheme))
utilruntime.Must(extensionsv1alpha1.AddToScheme(rscheme))
utilruntime.Must(batchv1.AddToScheme(rscheme))
utilruntime.Must(apiextv1.AddToScheme(rscheme))
utilruntime.Must(workloads.AddToScheme(rscheme))
utilruntime.Must(legacy.AddToScheme(rscheme))
}

type gvkNObjKey struct {
Expand Down
85 changes: 74 additions & 11 deletions controllers/apps/transformer_component_deletion.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ package apps

import (
"fmt"
"reflect"
"time"

batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/types"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1"
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
"github.com/apecloud/kubeblocks/apis/workloads/legacy"
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1alpha1"
"github.com/apecloud/kubeblocks/pkg/constant"
"github.com/apecloud/kubeblocks/pkg/controller/component"
Expand All @@ -59,11 +62,13 @@ func (t *componentDeletionTransformer) Transform(ctx graph.TransformContext, dag
}
graphCli, _ := transCtx.Client.(model.GraphClient)
comp := transCtx.Component
clusterMissing := false
cluster, err := t.getCluster(transCtx, comp)
if err != nil {
if !apierrors.IsNotFound(err) {
return newRequeueError(requeueDuration, err.Error())
}
clusterMissing = true
// Cluster has been deleted, use a default cluster with Delete termination policy
// to allow the component deletion to proceed
cluster = t.newDefaultCluster(comp)
Expand All @@ -79,16 +84,18 @@ func (t *componentDeletionTransformer) Transform(ctx graph.TransformContext, dag
}

// step2: do the pre-terminate action if needed
if err := component.ReconcileCompPreTerminate(reqCtx, transCtx.Client, graphCli, cluster, comp, dag); err != nil {
reqCtx.Log.Info("failed to reconcile component pre-terminate action", "component", comp.Name, "error", err)
if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeExpectedInProcess) {
// waiting for the preTerminate action to be done, and watch the action finish event to trigger the next reconcile
return nil
}
if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeRequeue) {
return newRequeueError(time.Second*1, "request to requeue the component pre-terminate action")
if !clusterMissing {
if err := component.ReconcileCompPreTerminate(reqCtx, transCtx.Client, graphCli, cluster, comp, dag); err != nil {
reqCtx.Log.Info("failed to reconcile component pre-terminate action", "component", comp.Name, "error", err)
if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeExpectedInProcess) {
// waiting for the preTerminate action to be done, and watch the action finish event to trigger the next reconcile
return nil
}
if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeRequeue) {
return newRequeueError(time.Second*1, "request to requeue the component pre-terminate action")
}
return err
}
return err
}

// step3: delete the sub-resources
Expand All @@ -108,7 +115,11 @@ func (t *componentDeletionTransformer) Transform(ctx graph.TransformContext, dag
// handleCompDeleteWhenScaleIn handles the component deletion when scale-in, this scenario will delete all the sub-resources owned by the component by default.
func (t *componentDeletionTransformer) handleCompDeleteWhenScaleIn(transCtx *componentTransformContext, graphCli model.GraphClient,
dag *graph.DAG, comp *appsv1alpha1.Component, matchLabels map[string]string) error {
return t.deleteCompResources(transCtx, graphCli, dag, comp, matchLabels, kindsForCompWipeOut())
toDeleteKinds, err := compDeleteKindsWithLegacyRSM(transCtx, graphCli, kindsForCompWipeOut())
if err != nil {
return err
}
return t.deleteCompResources(transCtx, graphCli, dag, comp, matchLabels, toDeleteKinds)
}

// handleCompDeleteWhenClusterDelete handles the component deletion when the cluster is being deleted, the sub-resources owned by the component depends on the cluster's TerminationPolicy.
Expand All @@ -121,6 +132,11 @@ func (t *componentDeletionTransformer) handleCompDeleteWhenClusterDelete(transCt
case appsv1alpha1.WipeOut:
toDeleteKinds = kindsForCompWipeOut()
}
var err error
toDeleteKinds, err = compDeleteKindsWithLegacyRSM(transCtx, graphCli, toDeleteKinds)
if err != nil {
return err
}

return t.deleteCompResources(transCtx, graphCli, dag, comp, matchLabels, toDeleteKinds)
}
Expand All @@ -132,6 +148,13 @@ func (t *componentDeletionTransformer) deleteCompResources(transCtx *componentTr
if err != nil {
return newRequeueError(requeueDuration, err.Error())
}
dependents, err := readCompOwnedObjects(transCtx, comp, toDeleteKinds...)
if err != nil {
return newRequeueError(requeueDuration, err.Error())
}
for key, object := range dependents {
snapshot[key] = object
}
if len(snapshot) > 0 {
// delete the sub-resources owned by the component before deleting the component
for _, object := range snapshot {
Expand Down Expand Up @@ -181,6 +204,45 @@ func (t *componentDeletionTransformer) newDefaultCluster(comp *appsv1alpha1.Comp
}
}

func readCompOwnedObjects(transCtx *componentTransformContext, comp *appsv1alpha1.Component, kinds ...client.ObjectList) (model.ObjectSnapshot, error) {
snapshot := make(model.ObjectSnapshot)
for _, list := range kinds {
if err := transCtx.GetClient().List(transCtx.GetContext(), list, client.InNamespace(comp.Namespace)); err != nil {
if model.IsPolicyV1DiscoveryNotFoundError(err) {
continue
}
return nil, err
}
items := reflect.ValueOf(list).Elem().FieldByName("Items")
if !items.IsValid() {
return nil, fmt.Errorf("ObjectList has no Items field: %s", list.GetObjectKind().GroupVersionKind().String())
}
for i := 0; i < items.Len(); i++ {
object := items.Index(i).Addr().Interface().(client.Object)
if !model.IsOwnerOf(comp, object) {
continue
}
key, err := model.GetGVKName(object)
if err != nil {
return nil, err
}
snapshot[*key] = object
}
}
return snapshot, nil
}

func compDeleteKindsWithLegacyRSM(transCtx *componentTransformContext, graphCli model.GraphClient, kinds []client.ObjectList) ([]client.ObjectList, error) {
exists, err := legacyCRDExists(transCtx.Context, graphCli)
if err != nil {
return nil, err
}
if exists {
kinds = append(kinds, &legacy.ReplicatedStateMachineList{})
}
return kinds, nil
}

func compOwnedKinds() []client.ObjectList {
return []client.ObjectList{
&workloads.InstanceSetList{},
Expand All @@ -191,6 +253,7 @@ func compOwnedKinds() []client.ObjectList {
&dpv1alpha1.RestoreList{},
&dpv1alpha1.BackupList{},
&appsv1alpha1.ConfigurationList{},
&policyv1.PodDisruptionBudgetList{},
}
}

Expand Down
Loading
Loading