Skip to content
Merged
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
2 changes: 0 additions & 2 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ func init() {
viper.SetDefault("VOLUMESNAPSHOT_API_BETA", false)
viper.SetDefault(constant.KBToolsImage, "apecloud/kubeblocks-tools:latest")
viper.SetDefault("KUBEBLOCKS_SERVICEACCOUNT_NAME", "kubeblocks")
viper.SetDefault(constant.ConfigManagerGPRCPortEnv, 9901)
viper.SetDefault("CONFIG_MANAGER_LOG_LEVEL", "info")
viper.SetDefault(constant.CfgKeyCtrlrMgrNS, "default")
viper.SetDefault(constant.CfgHostPortConfigMapName, "kubeblocks-host-ports")
viper.SetDefault(constant.CfgHostPortIncludeRanges, "55000-59999")
Expand Down
117 changes: 117 additions & 0 deletions controllers/parameters/componentdrivenparameter_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"reflect"
"slices"
"strconv"

"github.com/imdario/mergo"
"github.com/pkg/errors"
Expand All @@ -38,6 +39,8 @@ import (

appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
parametersv1alpha1 "github.com/apecloud/kubeblocks/apis/parameters/v1alpha1"
workloads "github.com/apecloud/kubeblocks/apis/workloads/v1"
reconfigurectrl "github.com/apecloud/kubeblocks/controllers/parameters/reconfigure"
"github.com/apecloud/kubeblocks/pkg/constant"
"github.com/apecloud/kubeblocks/pkg/controller/builder"
"github.com/apecloud/kubeblocks/pkg/controller/component"
Expand Down Expand Up @@ -104,8 +107,18 @@ func (r *ComponentDrivenParameterReconciler) reconcile(reqCtx intctrlutil.Reques
return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "")
}
if model.IsObjectDeleting(component) {
if err = r.syncLegacyConfigManagerRequirement(reqCtx, component, false); err != nil {
return intctrlutil.RequeueWithError(err, reqCtx.Log, errors.Wrap(err, "failed to clear legacy config-manager compatibility annotation").Error())
}
return r.delete(reqCtx, existingObject)
}
required, err := resolveLegacyConfigManagerRequirement(reqCtx.Ctx, r.Client, component)
if err != nil {
return intctrlutil.RequeueWithError(err, reqCtx.Log, "")
}
if err = r.syncLegacyConfigManagerRequirement(reqCtx, component, required); err != nil {
return intctrlutil.RequeueWithError(err, reqCtx.Log, errors.Wrap(err, "failed to sync legacy config-manager compatibility annotation").Error())
}
if expectedObject, err = buildComponentParameter(reqCtx, r.Client, component); err != nil {
return intctrlutil.RequeueWithError(err, reqCtx.Log, "")
}
Expand Down Expand Up @@ -151,6 +164,67 @@ func (r *ComponentDrivenParameterReconciler) update(reqCtx intctrlutil.RequestCt
return intctrlutil.Reconciled()
}

func (r *ComponentDrivenParameterReconciler) syncLegacyConfigManagerRequirement(reqCtx intctrlutil.RequestCtx, comp *appsv1.Component, required bool) error {
clusterName, _ := component.GetClusterName(comp)
clusterKey := types.NamespacedName{Namespace: comp.Namespace, Name: clusterName}
cluster := &appsv1.Cluster{}
if err := r.Client.Get(reqCtx.Ctx, clusterKey, cluster); err != nil {
return client.IgnoreNotFound(err)
}
aggregated, err := r.resolveClusterLegacyConfigManagerRequirement(reqCtx.Ctx, cluster, comp, required)
if err != nil {
return err
}
desiredValue := strconv.FormatBool(aggregated)
currentValue := ""
if cluster.Annotations != nil {
currentValue = cluster.Annotations[constant.LegacyConfigManagerRequiredAnnotationKey]
}
if currentValue == desiredValue {
return nil
}
patch := client.MergeFrom(cluster.DeepCopy())
if cluster.Annotations == nil {
cluster.Annotations = map[string]string{}
}
// Keep an explicit "false" marker instead of deleting the key. The compatible
// config-manager cleanup flow treats a missing key as "unknown, keep legacy
// resources" during controller upgrade races, while "false" means cleanup is
// now safe when the workload naturally recreates Pods.
cluster.Annotations[constant.LegacyConfigManagerRequiredAnnotationKey] = desiredValue
return r.Client.Patch(reqCtx.Ctx, cluster, patch)
}

func (r *ComponentDrivenParameterReconciler) resolveClusterLegacyConfigManagerRequirement(ctx context.Context, cluster *appsv1.Cluster, currentComp *appsv1.Component, currentRequired bool) (bool, error) {
if cluster == nil {
return false, nil
}
compList := &appsv1.ComponentList{}
if err := r.Client.List(ctx, compList, client.InNamespace(cluster.Namespace), client.MatchingLabels{constant.AppInstanceLabelKey: cluster.Name}); err != nil {
return false, err
}
for i := range compList.Items {
comp := &compList.Items[i]
if currentComp != nil && comp.Name == currentComp.Name {
if currentRequired && !model.IsObjectDeleting(comp) {
return true, nil
}
continue
}
if model.IsObjectDeleting(comp) {
continue
}
required, err := resolveLegacyConfigManagerRequirement(ctx, r.Client, comp)
if err != nil {
return false, err
}
if required {
return true, nil
}
}
return false, nil
}

func runningComponentParameter(reqCtx intctrlutil.RequestCtx, reader client.Reader, comp *appsv1.Component) (*parametersv1alpha1.ComponentParameter, error) {
var componentParameter = &parametersv1alpha1.ComponentParameter{}

Expand Down Expand Up @@ -237,6 +311,49 @@ func buildComponentParameter(reqCtx intctrlutil.RequestCtx, reader client.Reader
return parameterObj, err
}

// resolveLegacyConfigManagerRequirement reports whether this component still depends on the
// legacy config-manager compatibility path. The requirement exists only when the parameters
// definition still uses legacy actions and the running workload still carries the injected
// config-manager sidecar from older releases.
func resolveLegacyConfigManagerRequirement(ctx context.Context, reader client.Reader, comp *appsv1.Component) (bool, error) {
cmpd, err := getCompDefinition(ctx, reader, comp.Spec.CompDef)
if err != nil {
return false, err
}
_, paramsDefs, err := parameters.ResolveCmpdParametersDefs(ctx, reader, cmpd)
if err != nil {
return false, err
}
if !parameters.LegacyConfigManagerRequiredForParamsDefs(paramsDefs) {
return false, nil
}
its, err := resolveLegacyConfigManagerWorkload(ctx, reader, comp)
if client.IgnoreNotFound(err) != nil {
return false, err
}
return reconfigurectrl.HasLegacyConfigManagerRuntime(its), nil
}

func resolveLegacyConfigManagerWorkload(ctx context.Context, reader client.Reader, comp *appsv1.Component) (*workloads.InstanceSet, error) {
clusterName, err := component.GetClusterName(comp)
if err != nil {
return nil, err
}
componentName, err := component.ShortName(clusterName, comp.Name)
if err != nil {
return nil, err
}
its := &workloads.InstanceSet{}
key := types.NamespacedName{
Namespace: comp.Namespace,
Name: constant.GenerateWorkloadNamePattern(clusterName, componentName),
}
if err := reader.Get(ctx, key, its); err != nil {
return nil, err
}
return its, nil
}

func handleCustomParameterTemplate(ctx context.Context, reader client.Reader, annotations map[string]string, specs []parametersv1alpha1.ConfigTemplateItemDetail) error {
if len(annotations) == 0 {
return nil
Expand Down
Loading
Loading