diff --git a/controllers/apps/component_controller_test.go b/controllers/apps/component_controller_test.go index e8b3e3c4d10..b61c0586e77 100644 --- a/controllers/apps/component_controller_test.go +++ b/controllers/apps/component_controller_test.go @@ -1329,7 +1329,7 @@ var _ = Describe("Component Controller", func() { Name: compObj.Name, } Eventually(testapps.CheckObj(&testCtx, itsKey, func(g Gomega, its *workloads.InstanceSet) { - envVars, _ := buildEnvVarsNData(nil, targetEnvVars, false) + envVars, _ := buildEnvVarsNData(targetEnvVars) targetEnvVarsMapping := map[string]corev1.EnvVar{} for i, v := range envVars { targetEnvVarsMapping[v.Name] = envVars[i] @@ -1353,7 +1353,7 @@ var _ = Describe("Component Controller", func() { Name: constant.GenerateClusterComponentEnvPattern(clusterObj.Name, compName), } Eventually(testapps.CheckObj(&testCtx, envCMKey, func(g Gomega, cm *corev1.ConfigMap) { - _, envData := buildEnvVarsNData(nil, targetEnvVars, false) + _, envData := buildEnvVarsNData(targetEnvVars) for k, v := range envData { Expect(cm.Data).Should(HaveKeyWithValue(k, v)) } diff --git a/controllers/apps/configuration/config_reconcile_wrapper.go b/controllers/apps/configuration/config_reconcile_wrapper.go index fe90d75b62a..505f6458759 100644 --- a/controllers/apps/configuration/config_reconcile_wrapper.go +++ b/controllers/apps/configuration/config_reconcile_wrapper.go @@ -20,19 +20,21 @@ along with this program. If not, see . package configuration import ( + "context" + corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" workloads "github.com/apecloud/kubeblocks/apis/workloads/v1" "github.com/apecloud/kubeblocks/pkg/controller/component" configctrl "github.com/apecloud/kubeblocks/pkg/controller/configuration" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" "github.com/apecloud/kubeblocks/pkg/generics" ) type configReconcileContext struct { configctrl.ResourceFetcher[configReconcileContext] + ctx context.Context Name string MatchingLabels client.MatchingLabels ConfigMap *corev1.ConfigMap @@ -40,17 +42,15 @@ type configReconcileContext struct { Containers []string InstanceSetList []workloads.InstanceSet - - reqCtx intctrlutil.RequestCtx } -func newConfigReconcileContext(resourceCtx *configctrl.ResourceCtx, +func newConfigReconcileContext(ctx context.Context, + resourceCtx *configctrl.ResourceCtx, cm *corev1.ConfigMap, configSpecName string, - reqCtx intctrlutil.RequestCtx, matchingLabels client.MatchingLabels) *configReconcileContext { configContext := configReconcileContext{ - reqCtx: reqCtx, + ctx: ctx, ConfigMap: cm, Name: configSpecName, MatchingLabels: matchingLabels, @@ -84,13 +84,8 @@ func (c *configReconcileContext) Workload() *configReconcileContext { func (c *configReconcileContext) SynthesizedComponent() *configReconcileContext { return c.Wrap(func() (err error) { - if c.ComponentDefObj != nil && c.ComponentObj != nil && len(c.ComponentObj.Spec.CompDef) > 0 { - // build synthesized component for native component - c.BuiltinComponent, err = component.BuildSynthesizedComponent(c.reqCtx, c.Client, c.ClusterObj, c.ComponentDefObj, c.ComponentObj) - } else { - // build synthesized component for generated component - c.BuiltinComponent, err = component.BuildSynthesizedComponentWrapper(c.reqCtx, c.Client, c.ClusterObj, c.ClusterComObj) - } + // build synthesized component for the component + c.BuiltinComponent, err = component.BuildSynthesizedComponent(c.ctx, c.Client, c.ComponentDefObj, c.ComponentObj, c.ClusterObj) return err }) } diff --git a/controllers/apps/configuration/configuration_controller.go b/controllers/apps/configuration/configuration_controller.go index 6470d2faa35..dcfa9b77d8e 100644 --- a/controllers/apps/configuration/configuration_controller.go +++ b/controllers/apps/configuration/configuration_controller.go @@ -117,7 +117,7 @@ func (r *ConfigurationReconciler) Reconcile(ctx context.Context, req ctrl.Reques if fetcherTask.ClusterComObj == nil || fetcherTask.ComponentObj == nil { return r.failWithInvalidComponent(config, reqCtx) } - if err := r.runTasks(TaskContext{config, reqCtx, fetcherTask}, tasks); err != nil { + if err := r.runTasks(TaskContext{config, ctx, fetcherTask}, tasks); err != nil { return intctrlutil.CheckedRequeueWithError(err, reqCtx.Log, "failed to run configuration reconcile task.") } if !isAllReady(config) { @@ -151,20 +151,14 @@ func (r *ConfigurationReconciler) runTasks(taskCtx TaskContext, tasks []Task) (e var ( errs []error synthesizedComp *component.SynthesizedComponent - - ctx = taskCtx.reqCtx.Ctx - configuration = taskCtx.configuration + configuration = taskCtx.configuration ) - if len(taskCtx.fetcher.ComponentObj.Spec.CompDef) == 0 { - // build synthesized component for generated component - synthesizedComp, err = component.BuildSynthesizedComponentWrapper(taskCtx.reqCtx, r.Client, taskCtx.fetcher.ClusterObj, taskCtx.fetcher.ClusterComObj) - } else { - // build synthesized component for native component - synthesizedComp, err = component.BuildSynthesizedComponent(taskCtx.reqCtx, r.Client, taskCtx.fetcher.ClusterObj, taskCtx.fetcher.ComponentDefObj, taskCtx.fetcher.ComponentObj) - if err == nil { - err = buildTemplateVars(taskCtx.reqCtx.Ctx, r.Client, taskCtx.fetcher.ComponentDefObj, synthesizedComp) - } + // build synthesized component for the component + synthesizedComp, err = component.BuildSynthesizedComponent(taskCtx.ctx, r.Client, + taskCtx.fetcher.ComponentDefObj, taskCtx.fetcher.ComponentObj, taskCtx.fetcher.ClusterObj) + if err == nil { + err = buildTemplateVars(taskCtx.ctx, r.Client, taskCtx.fetcher.ComponentDefObj, synthesizedComp) } if err != nil { return err @@ -184,7 +178,7 @@ func (r *ConfigurationReconciler) runTasks(taskCtx TaskContext, tasks []Task) (e if len(errs) > 0 { configuration.Status.Message = utilerrors.NewAggregate(errs).Error() } - if err := r.Client.Status().Patch(ctx, configuration, patch); err != nil { + if err := r.Client.Status().Patch(taskCtx.ctx, configuration, patch); err != nil { errs = append(errs, err) } if len(errs) == 0 { diff --git a/controllers/apps/configuration/configuration_test.go b/controllers/apps/configuration/configuration_test.go index c59611709cd..1e2cdb65b35 100644 --- a/controllers/apps/configuration/configuration_test.go +++ b/controllers/apps/configuration/configuration_test.go @@ -28,7 +28,6 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1" @@ -38,7 +37,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/controller/builder" "github.com/apecloud/kubeblocks/pkg/controller/component" configctrl "github.com/apecloud/kubeblocks/pkg/controller/configuration" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -147,11 +145,7 @@ func mockReconcileResource() (*corev1.ConfigMap, *appsv1beta1.ConfigConstraint, AddAnnotations(core.GenerateTPLUniqLabelKeyWithConfig(configSpecName), configmap.Name). Create(&testCtx).GetObject() - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Log: log.FromContext(testCtx.Ctx), - } - synthesizedComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, clusterObj, compDefObj, compObj) + synthesizedComp, err := component.BuildSynthesizedComponent(testCtx.Ctx, testCtx.Cli, compDefObj, compObj, clusterObj) Expect(err).ShouldNot(HaveOccurred()) return configmap, constraint, clusterObj, compObj, synthesizedComp diff --git a/controllers/apps/configuration/reconcile_task.go b/controllers/apps/configuration/reconcile_task.go index 8930df4a733..22e2f994226 100644 --- a/controllers/apps/configuration/reconcile_task.go +++ b/controllers/apps/configuration/reconcile_task.go @@ -20,6 +20,7 @@ along with this program. If not, see . package configuration import ( + "context" "strconv" corev1 "k8s.io/api/core/v1" @@ -46,7 +47,7 @@ type Task struct { type TaskContext struct { configuration *appsv1alpha1.Configuration - reqCtx intctrlutil.RequestCtx + ctx context.Context fetcher *Task } diff --git a/controllers/apps/configuration/reconfigure_controller.go b/controllers/apps/configuration/reconfigure_controller.go index d8c3e8e0bff..232f3525dbc 100644 --- a/controllers/apps/configuration/reconfigure_controller.go +++ b/controllers/apps/configuration/reconfigure_controller.go @@ -185,6 +185,7 @@ func (r *ReconfigureReconciler) sync(reqCtx intctrlutil.RequestCtx, configMap *c } reconcileContext := newConfigReconcileContext( + reqCtx.Ctx, &configctrl.ResourceCtx{ Context: reqCtx.Ctx, Client: r.Client, @@ -194,7 +195,6 @@ func (r *ReconfigureReconciler) sync(reqCtx intctrlutil.RequestCtx, configMap *c }, configMap, resources.configSpec.Name, - reqCtx, resources.componentMatchLabels()) if err := reconcileContext.GetRelatedObjects(); err != nil { return intctrlutil.RequeueWithErrorAndRecordEvent(configMap, r.Recorder, err, reqCtx.Log) diff --git a/controllers/apps/operations/rebuild_instance.go b/controllers/apps/operations/rebuild_instance.go index 8f462bfdbe4..d7c695a7cfe 100644 --- a/controllers/apps/operations/rebuild_instance.go +++ b/controllers/apps/operations/rebuild_instance.go @@ -20,6 +20,7 @@ along with this program. If not, see . package operations import ( + "context" "fmt" "reflect" "strings" @@ -94,7 +95,7 @@ func (r rebuildInstanceOpsHandler) Action(reqCtx intctrlutil.RequestCtx, cli cli if err := cli.Get(reqCtx.Ctx, client.ObjectKey{Name: ins.Name, Namespace: opsRes.Cluster.Namespace}, targetPod); err != nil { return err } - synthesizedComp, err = r.buildSynthesizedComponent(reqCtx, cli, opsRes.Cluster, targetPod.Labels[constant.KBAppComponentLabelKey]) + synthesizedComp, err = r.buildSynthesizedComponent(reqCtx.Ctx, cli, opsRes.Cluster, targetPod.Labels[constant.KBAppComponentLabelKey]) if err != nil { return err } @@ -417,7 +418,7 @@ func (r rebuildInstanceOpsHandler) checkProgressForScalingOutPods(reqCtx intctrl failedCount int completedCount int ) - synthesizedComp, err := r.buildSynthesizedComponent(reqCtx, cli, opsRes.Cluster, rebuildInstance.ComponentName) + synthesizedComp, err := r.buildSynthesizedComponent(reqCtx.Ctx, cli, opsRes.Cluster, rebuildInstance.ComponentName) if err != nil { return 0, 0, nil, err } @@ -510,20 +511,15 @@ func (r rebuildInstanceOpsHandler) getScalingOutPodNameFromMessage(progressMsg s return strings.Replace(strArr[0], scalingOutPodPrefixMsg+": ", "", 1) } -func (r rebuildInstanceOpsHandler) buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, +func (r rebuildInstanceOpsHandler) buildSynthesizedComponent(ctx context.Context, cli client.Client, cluster *appsv1.Cluster, componentName string) (*component.SynthesizedComponent, error) { - compSpec := getComponentSpecOrShardingTemplate(cluster, componentName) - if compSpec.ComponentDef == "" { - // TODO: remove after 0.9 - return component.BuildSynthesizedComponentWrapper(reqCtx, cli, cluster, compSpec) - } - comp, compDef, err := component.GetCompNCompDefByName(reqCtx.Ctx, cli, cluster.Namespace, constant.GenerateClusterComponentName(cluster.Name, componentName)) + comp, compDef, err := component.GetCompNCompDefByName(ctx, cli, cluster.Namespace, constant.GenerateClusterComponentName(cluster.Name, componentName)) if err != nil { return nil, err } - return component.BuildSynthesizedComponent(reqCtx, cli, cluster, compDef, comp) + return component.BuildSynthesizedComponent(ctx, cli, compDef, comp, cluster) } func (r rebuildInstanceOpsHandler) prepareInplaceRebuildHelper(reqCtx intctrlutil.RequestCtx, @@ -563,7 +559,7 @@ func (r rebuildInstanceOpsHandler) prepareInplaceRebuildHelper(reqCtx intctrluti if err = cli.Get(reqCtx.Ctx, client.ObjectKey{Name: instance.Name, Namespace: opsRes.Cluster.Namespace}, targetPod); err != nil { return nil, err } - synthesizedComp, err = r.buildSynthesizedComponent(reqCtx, cli, opsRes.Cluster, targetPod.Labels[constant.KBAppComponentLabelKey]) + synthesizedComp, err = r.buildSynthesizedComponent(reqCtx.Ctx, cli, opsRes.Cluster, targetPod.Labels[constant.KBAppComponentLabelKey]) if err != nil { return nil, err } diff --git a/controllers/apps/operations/switchover.go b/controllers/apps/operations/switchover.go index 59641c030ff..e33f2a0da93 100644 --- a/controllers/apps/operations/switchover.go +++ b/controllers/apps/operations/switchover.go @@ -20,6 +20,7 @@ along with this program. If not, see . package operations import ( + "context" "encoding/json" "fmt" "reflect" @@ -67,7 +68,7 @@ func (r switchoverOpsHandler) ActionStartedCondition(reqCtx intctrlutil.RequestC switchoverMessageMap := make(map[string]SwitchoverMessage) for _, switchover := range opsRes.OpsRequest.Spec.SwitchoverList { compSpec := opsRes.Cluster.Spec.GetComponentByName(switchover.ComponentName) - synthesizedComp, err := buildSynthesizedComp(reqCtx, cli, opsRes, compSpec) + synthesizedComp, err := buildSynthesizedComp(reqCtx.Ctx, cli, opsRes, compSpec) if err != nil { return nil, err } @@ -133,7 +134,7 @@ func doSwitchoverComponents(reqCtx intctrlutil.RequestCtx, cli client.Client, op } for _, switchover := range switchoverList { compSpec := opsRes.Cluster.Spec.GetComponentByName(switchover.ComponentName) - synthesizedComp, err := buildSynthesizedComp(reqCtx, cli, opsRes, compSpec) + synthesizedComp, err := buildSynthesizedComp(reqCtx.Ctx, cli, opsRes, compSpec) if err != nil { return err } @@ -227,7 +228,7 @@ func handleSwitchoverProgress(reqCtx intctrlutil.RequestCtx, cli client.Client, Message: fmt.Sprintf("waiting for component %s pod role label consistency after switchover", switchover.ComponentName), } compSpec := opsRes.Cluster.Spec.GetComponentByName(switchover.ComponentName) - synthesizedComp, errBuild := component.BuildSynthesizedComponentWrapper(reqCtx, cli, opsRes.Cluster, compSpec) + synthesizedComp, errBuild := buildSynthesizedComp(reqCtx.Ctx, cli, opsRes, compSpec) if errBuild != nil { checkRoleLabelProcessDetail.Message = fmt.Sprintf("handleSwitchoverProgress build synthesizedComponent %s failed", switchover.ComponentName) checkRoleLabelProcessDetail.Status = appsv1alpha1.FailedProgressStatus @@ -300,17 +301,12 @@ func setComponentSwitchoverProgressDetails(recorder record.EventRecorder, } } -// buildSynthesizedComp builds synthesized component for native component or generated component. -func buildSynthesizedComp(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource, clusterCompSpec *appsv1.ClusterComponentSpec) (*component.SynthesizedComponent, error) { - if len(clusterCompSpec.ComponentDef) > 0 { - compObj, compDefObj, err := component.GetCompNCompDefByName(reqCtx.Ctx, cli, - opsRes.Cluster.Namespace, constant.GenerateClusterComponentName(opsRes.Cluster.Name, clusterCompSpec.Name)) - if err != nil { - return nil, err - } - // build synthesized component for native component - return component.BuildSynthesizedComponent(reqCtx, cli, opsRes.Cluster, compDefObj, compObj) +func buildSynthesizedComp(ctx context.Context, cli client.Client, opsRes *OpsResource, clusterCompSpec *appsv1.ClusterComponentSpec) (*component.SynthesizedComponent, error) { + compObj, compDefObj, err := component.GetCompNCompDefByName(ctx, cli, + opsRes.Cluster.Namespace, constant.GenerateClusterComponentName(opsRes.Cluster.Name, clusterCompSpec.Name)) + if err != nil { + return nil, err } - // build synthesized component for generated component - return component.BuildSynthesizedComponentWrapper(reqCtx, cli, opsRes.Cluster, clusterCompSpec) + // build synthesized component for the component + return component.BuildSynthesizedComponent(ctx, cli, compDefObj, compObj, opsRes.Cluster) } diff --git a/controllers/apps/transformer_cluster_component_status.go b/controllers/apps/transformer_cluster_component_status.go index 5c3f500f4a7..c16db85dea7 100644 --- a/controllers/apps/transformer_cluster_component_status.go +++ b/controllers/apps/transformer_cluster_component_status.go @@ -55,7 +55,6 @@ func (t *clusterComponentStatusTransformer) reconcileComponentsStatus(transCtx * if cluster.Status.Components == nil { cluster.Status.Components = make(map[string]appsv1.ClusterComponentStatus) } - // We cannot use cluster.status.components here because of simplified API generated component is not in it. for _, compSpec := range transCtx.ComponentSpecs { compKey := types.NamespacedName{ Namespace: cluster.Namespace, diff --git a/controllers/apps/transformer_component_account_provision.go b/controllers/apps/transformer_component_account_provision.go index 60d24e1eb9e..afc6c7aff1c 100644 --- a/controllers/apps/transformer_component_account_provision.go +++ b/controllers/apps/transformer_component_account_provision.go @@ -72,7 +72,7 @@ func (t *componentAccountProvisionTransformer) Transform(ctx graph.TransformCont } lifecycleActions := transCtx.CompDef.Spec.LifecycleActions - if !component.IsGenerated(transCtx.Component) && (lifecycleActions == nil || lifecycleActions.AccountProvision == nil) { + if lifecycleActions == nil || lifecycleActions.AccountProvision == nil { return nil } diff --git a/controllers/apps/transformer_component_load_resources.go b/controllers/apps/transformer_component_load_resources.go index 1c71b2d09f3..deec5ce05e3 100644 --- a/controllers/apps/transformer_component_load_resources.go +++ b/controllers/apps/transformer_component_load_resources.go @@ -27,7 +27,6 @@ import ( appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controller/graph" - ictrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) // componentLoadResourcesTransformer handles referenced resources validation and load them into context @@ -56,31 +55,7 @@ func (t *componentLoadResourcesTransformer) Transform(ctx graph.TransformContext } transCtx.Cluster = cluster - if component.IsGenerated(transCtx.ComponentOrig) { - err = t.transformForGeneratedComponent(transCtx) - } else { - err = t.transformForNativeComponent(transCtx) - } - return err -} - -func (t *componentLoadResourcesTransformer) transformForGeneratedComponent(transCtx *componentTransformContext) error { - reqCtx := ictrlutil.RequestCtx{ - Ctx: transCtx.Context, - Log: transCtx.Logger, - Recorder: transCtx.EventRecorder, - } - comp := transCtx.Component - - compDef, synthesizedComp, err := component.BuildSynthesizedComponent4Generated(reqCtx, transCtx.Client, transCtx.Cluster, comp) - if err != nil { - message := fmt.Sprintf("build synthesized component for %s failed: %s", comp.Name, err.Error()) - return newRequeueError(requeueDuration, message) - } - transCtx.CompDef = compDef - transCtx.SynthesizeComponent = synthesizedComp - - return nil + return t.transformForNativeComponent(transCtx) } func (t *componentLoadResourcesTransformer) transformForNativeComponent(transCtx *componentTransformContext) error { @@ -98,12 +73,7 @@ func (t *componentLoadResourcesTransformer) transformForNativeComponent(transCtx } transCtx.CompDef = compDef - reqCtx := ictrlutil.RequestCtx{ - Ctx: transCtx.Context, - Log: transCtx.Logger, - Recorder: transCtx.EventRecorder, - } - synthesizedComp, err := component.BuildSynthesizedComponent(reqCtx, transCtx.Client, transCtx.Cluster, compDef, comp) + synthesizedComp, err := component.BuildSynthesizedComponent(ctx, transCtx.Client, compDef, comp, transCtx.Cluster) if err != nil { message := fmt.Sprintf("build synthesized component for %s failed: %s", comp.Name, err.Error()) return newRequeueError(requeueDuration, message) diff --git a/controllers/apps/transformer_component_pre_terminate.go b/controllers/apps/transformer_component_pre_terminate.go index 71c58482b9b..f72fac9361c 100644 --- a/controllers/apps/transformer_component_pre_terminate.go +++ b/controllers/apps/transformer_component_pre_terminate.go @@ -144,12 +144,7 @@ func (t *componentPreTerminateTransformer) synthesizedComponent(transCtx *compon return nil, newRequeueError(requeueDuration, err.Error()) } - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: transCtx.Logger, - Recorder: transCtx.EventRecorder, - } - synthesizedComp, err := component.BuildSynthesizedComponent(reqCtx, cli, cluster, compDef, comp) + synthesizedComp, err := component.BuildSynthesizedComponent(ctx, cli, compDef, comp, cluster) if err != nil { return nil, newRequeueError(requeueDuration, fmt.Sprintf("build synthesized component failed at pre-terminate transformer: %s", err.Error())) diff --git a/controllers/apps/transformer_component_rbac_test.go b/controllers/apps/transformer_component_rbac_test.go index 2aa0e3e08ac..ae63f0e9d33 100644 --- a/controllers/apps/transformer_component_rbac_test.go +++ b/controllers/apps/transformer_component_rbac_test.go @@ -33,7 +33,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/controller/factory" "github.com/apecloud/kubeblocks/pkg/controller/graph" "github.com/apecloud/kubeblocks/pkg/controller/model" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" viper "github.com/apecloud/kubeblocks/pkg/viperx" ) @@ -86,11 +85,7 @@ var _ = Describe("object rbac transformer test.", func() { graphCli = model.NewGraphClient(k8sClient) - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - synthesizedComponent, err := component.BuildSynthesizedComponent(reqCtx, k8sClient, cluster, compDefObj, compObj) + synthesizedComponent, err := component.BuildSynthesizedComponent(ctx, k8sClient, compDefObj, compObj, cluster) Expect(err).Should(Succeed()) transCtx = &componentTransformContext{ diff --git a/controllers/apps/transformer_component_vars.go b/controllers/apps/transformer_component_vars.go index 2d9d759c592..b0ab0b13a09 100644 --- a/controllers/apps/transformer_component_vars.go +++ b/controllers/apps/transformer_component_vars.go @@ -31,7 +31,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" - workloads "github.com/apecloud/kubeblocks/apis/workloads/v1" "github.com/apecloud/kubeblocks/pkg/common" "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/builder" @@ -60,27 +59,15 @@ func (t *componentVarsTransformer) Transform(ctx graph.TransformContext, dag *gr reader := &varsReader{transCtx.Client, graphCli, dag} synthesizedComp := transCtx.SynthesizeComponent - legacy, err := generatedComponent4LegacyCluster(transCtx) - if err != nil { - return err - } - - var templateVars map[string]any - var envVars []corev1.EnvVar - if legacy { - templateVars, envVars, err = component.ResolveEnvVars4LegacyCluster(transCtx.Context, reader, - synthesizedComp, transCtx.CompDef.Spec.Vars) - } else { - templateVars, envVars, err = component.ResolveTemplateNEnvVars(transCtx.Context, reader, - synthesizedComp, transCtx.CompDef.Spec.Vars) - } + templateVars, envVars, err := component.ResolveTemplateNEnvVars(transCtx.Context, reader, + synthesizedComp, transCtx.CompDef.Spec.Vars) if err != nil { return err } // pass all direct value env vars through CM - envVars2, envData := buildEnvVarsNData(synthesizedComp, envVars, legacy) - setTemplateNEnvVars(synthesizedComp, templateVars, envVars2, legacy) + envVars2, envData := buildEnvVarsNData(envVars) + setTemplateNEnvVars(synthesizedComp, templateVars, envVars2) if err := createOrUpdateEnvConfigMap(ctx, dag, envData); err != nil { return err @@ -88,39 +75,13 @@ func (t *componentVarsTransformer) Transform(ctx graph.TransformContext, dag *gr return nil } -// generatedComponent4LegacyCluster checks whether the cluster to which this component belongs was created before 0.8. -func generatedComponent4LegacyCluster(transCtx *componentTransformContext) (bool, error) { - generated := component.IsGenerated(transCtx.ComponentOrig) - if !generated { - return false, nil - } - - synthesizedComp := transCtx.SynthesizeComponent - itsObj := &workloads.InstanceSet{} - itsKey := types.NamespacedName{ - Namespace: synthesizedComp.Namespace, - Name: constant.GenerateWorkloadNamePattern(synthesizedComp.ClusterName, synthesizedComp.Name), - } - if err := transCtx.Client.Get(transCtx.Context, itsKey, itsObj); err != nil { - return false, client.IgnoreNotFound(err) - } - - return !model.IsOwnerOf(transCtx.ComponentOrig, itsObj), nil -} - -func buildEnvVarsNData(synthesizedComp *component.SynthesizedComponent, vars []corev1.EnvVar, legacy bool) ([]corev1.EnvVar, map[string]string) { - envData := make(map[string]string) - - // for legacy cluster, don't move direct values into ConfigMap - if legacy { - return vars, envData - } - +func buildEnvVarsNData(vars []corev1.EnvVar) ([]corev1.EnvVar, map[string]string) { hasReference := func(v corev1.EnvVar) bool { return len(component.VarReferenceRegExp().FindAllStringSubmatchIndex(v.Value, -1)) > 0 } envVars := make([]corev1.EnvVar, 0) + envData := make(map[string]string) for i, v := range vars { if v.ValueFrom != nil || hasReference(v) { envVars = append(envVars, vars[i]) @@ -131,12 +92,8 @@ func buildEnvVarsNData(synthesizedComp *component.SynthesizedComponent, vars []c return envVars, envData } -func setTemplateNEnvVars(synthesizedComp *component.SynthesizedComponent, templateVars map[string]any, envVars []corev1.EnvVar, legacy bool) { +func setTemplateNEnvVars(synthesizedComp *component.SynthesizedComponent, templateVars map[string]any, envVars []corev1.EnvVar) { envSource := envConfigMapSource(synthesizedComp.ClusterName, synthesizedComp.Name) - if legacy { - envSource.ConfigMapRef.Optional = nil - } - synthesizedComp.TemplateVars = templateVars synthesizedComp.EnvVars = envVars synthesizedComp.EnvFromSources = []corev1.EnvFromSource{envSource} diff --git a/pkg/constant/const.go b/pkg/constant/const.go index 7eb5339c16c..70f836500fd 100644 --- a/pkg/constant/const.go +++ b/pkg/constant/const.go @@ -60,10 +60,9 @@ const ( ) const ( - KBPrefix = "KB" - KBLowerPrefix = "kb" - KBGeneratedVirtualCompDefPrefix = "KB_GENERATED_VIRTUAL_COMP_DEF" - SlashScalingLowerSuffix = "scaling" + KBPrefix = "KB" + KBLowerPrefix = "kb" + SlashScalingLowerSuffix = "scaling" ) const ( diff --git a/pkg/controller/component/component.go b/pkg/controller/component/component.go index a7747593b32..bbdfdaa2bf4 100644 --- a/pkg/controller/component/component.go +++ b/pkg/controller/component/component.go @@ -25,7 +25,6 @@ import ( "strconv" "strings" - "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" @@ -34,7 +33,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/builder" "github.com/apecloud/kubeblocks/pkg/controller/scheduling" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) func FullName(clusterName, compName string) string { @@ -57,26 +55,14 @@ func GetClusterUID(comp *appsv1.Component) (string, error) { return getCompLabelValue(comp, constant.KBAppClusterUIDLabelKey) } -// IsGenerated checks if the component is generated from legacy cluster definitions. -func IsGenerated(comp *appsv1.Component) bool { - return len(comp.Spec.CompDef) == 0 -} - // BuildComponent builds a new Component object from cluster component spec and definition. func BuildComponent(cluster *appsv1.Cluster, compSpec *appsv1.ClusterComponentSpec, labels, annotations map[string]string) (*appsv1.Component, error) { - compName := FullName(cluster.Name, compSpec.Name) - compDefName := func() string { - if strings.HasPrefix(compSpec.ComponentDef, constant.KBGeneratedVirtualCompDefPrefix) { - return "" - } - return compSpec.ComponentDef - }() schedulingPolicy, err := scheduling.BuildSchedulingPolicy(cluster, compSpec) if err != nil { return nil, err } - compBuilder := builder.NewComponentBuilder(cluster.Namespace, compName, compDefName). + compBuilder := builder.NewComponentBuilder(cluster.Namespace, FullName(cluster.Name, compSpec.Name), compSpec.ComponentDef). AddAnnotations(constant.KubeBlocksGenerationKey, strconv.FormatInt(cluster.Generation, 10)). AddLabelsInMap(constant.GetComponentWellKnownLabels(cluster.Name, compSpec.Name)). AddLabels(constant.KBAppClusterUIDLabelKey, string(cluster.UID)). @@ -93,6 +79,7 @@ func BuildComponent(cluster *appsv1.Cluster, compSpec *appsv1.ClusterComponentSp SetPodUpdatePolicy(compSpec.PodUpdatePolicy). SetVolumeClaimTemplates(compSpec.VolumeClaimTemplates). SetVolumes(compSpec.Volumes). + SetServices(compSpec.Services). SetConfigs(compSpec.Configs). SetServiceRefs(compSpec.ServiceRefs). SetTLSConfig(compSpec.TLS, compSpec.Issuer). @@ -113,39 +100,9 @@ func BuildComponent(cluster *appsv1.Cluster, compSpec *appsv1.ClusterComponentSp compBuilder.AddAnnotations(constant.KBAppMultiClusterPlacementKey, p) } } - if !IsGenerated(compBuilder.GetObject()) { - compBuilder.SetServices(compSpec.Services) - } return compBuilder.GetObject(), nil } -func getComponentDefinition(ctx context.Context, cli client.Reader, - spec *appsv1.ClusterComponentSpec) (*appsv1.ComponentDefinition, error) { - if len(spec.ComponentDef) > 0 { - compDef := &appsv1.ComponentDefinition{} - if err := cli.Get(ctx, types.NamespacedName{Name: spec.ComponentDef}, compDef); err != nil { - return nil, err - } - return compDef, nil - } - return nil, fmt.Errorf("the component definition is not provided") -} - -func getClusterCompSpec4Component(ctx context.Context, cli client.Reader, cluster *appsv1.Cluster, comp *appsv1.Component) (*appsv1.ClusterComponentSpec, error) { - compName, err := ShortName(cluster.Name, comp.Name) - if err != nil { - return nil, err - } - compSpec, err := intctrlutil.GetOriginalOrGeneratedComponentSpecByName(ctx, cli, cluster, compName) - if err != nil { - return nil, err - } - if compSpec != nil { - return compSpec, nil - } - return nil, fmt.Errorf("cluster component spec is not found for component: %s", comp.Name) -} - func getCompLabelValue(comp *appsv1.Component, label string) (string, error) { if comp.Labels == nil { return "", fmt.Errorf("required label %s is not provided, component: %s", label, comp.GetName()) diff --git a/pkg/controller/component/component_test.go b/pkg/controller/component/component_test.go index 6e4edb0473a..7a119d62c22 100644 --- a/pkg/controller/component/component_test.go +++ b/pkg/controller/component/component_test.go @@ -31,7 +31,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -67,10 +66,6 @@ var _ = Describe("Component", func() { } PIt("build serviceReference correctly", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } const ( name = "nginx" ns = "default" @@ -92,7 +87,7 @@ var _ = Describe("Component", func() { testapps.NginxImage: serviceDescriptor, } By("call build") - synthesizeComp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, compObj()) + synthesizeComp, err := BuildSynthesizedComponent(ctx, testCtx.Cli, compDef, compObj(), cluster) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) Expect(synthesizeComp.ServiceReferences).ShouldNot(BeNil()) @@ -108,7 +103,6 @@ var _ = Describe("Component", func() { _512m = resource.MustParse("512Mi") _1024m = resource.MustParse("1Gi") _2048m = resource.MustParse("2Gi") - reqCtx = intctrlutil.RequestCtx{Ctx: ctx, Log: logger} ) compDef.Spec.Runtime.Volumes = append(compDef.Spec.Runtime.Volumes, []corev1.Volume{ { @@ -156,7 +150,7 @@ var _ = Describe("Component", func() { } cluster.Spec.ComponentSpecs[0].Resources.Requests[corev1.ResourceMemory] = _512m cluster.Spec.ComponentSpecs[0].Resources.Limits[corev1.ResourceMemory] = _1024m - comp, err := BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef.DeepCopy(), compObj()) + comp, err := BuildSynthesizedComponent(ctx, testCtx.Cli, compDef.DeepCopy(), compObj(), cluster) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { @@ -177,7 +171,7 @@ var _ = Describe("Component", func() { By("without memory resource set") delete(cluster.Spec.ComponentSpecs[0].Resources.Requests, corev1.ResourceMemory) delete(cluster.Spec.ComponentSpecs[0].Resources.Limits, corev1.ResourceMemory) - comp, err = BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef.DeepCopy(), compObj()) + comp, err = BuildSynthesizedComponent(ctx, testCtx.Cli, compDef.DeepCopy(), compObj(), cluster) Expect(err).Should(Succeed()) Expect(comp).ShouldNot(BeNil()) for _, vol := range comp.PodSpec.Volumes { diff --git a/pkg/controller/component/service_descriptor_utils.go b/pkg/controller/component/service_descriptor_utils.go deleted file mode 100644 index 86c6b58956d..00000000000 --- a/pkg/controller/component/service_descriptor_utils.go +++ /dev/null @@ -1,332 +0,0 @@ -/* -Copyright (C) 2022-2024 ApeCloud Co., Ltd - -This file is part of KubeBlocks project - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -*/ - -package component - -import ( - "context" - "fmt" - "regexp" - "strings" - - "golang.org/x/exp/slices" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - - appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" - "github.com/apecloud/kubeblocks/pkg/constant" - "github.com/apecloud/kubeblocks/pkg/controller/builder" -) - -func buildServiceReferences(ctx context.Context, cli client.Reader, - synthesizedComp *SynthesizedComponent, compDef *appsv1.ComponentDefinition, comp *appsv1.Component) error { - if err := buildServiceReferencesWithoutResolve(ctx, cli, synthesizedComp, compDef, comp); err != nil { - return err - } - return resolveServiceReferences(ctx, cli, synthesizedComp) -} - -func buildServiceReferencesWithoutResolve(ctx context.Context, cli client.Reader, - synthesizedComp *SynthesizedComponent, compDef *appsv1.ComponentDefinition, comp *appsv1.Component) error { - if compDef == nil || comp == nil || len(compDef.Spec.ServiceRefDeclarations) == 0 { - return nil - } - - serviceRefs := map[string]*appsv1.ServiceRef{} - for i, serviceRef := range comp.Spec.ServiceRefs { - serviceRefs[serviceRef.Name] = &comp.Spec.ServiceRefs[i] - } - - serviceReferences := make(map[string]*appsv1.ServiceDescriptor, len(compDef.Spec.ServiceRefDeclarations)) - for _, serviceRefDecl := range compDef.Spec.ServiceRefDeclarations { - serviceRef, ok := serviceRefs[serviceRefDecl.Name] - if !ok { - if IsGenerated(comp) || (serviceRefDecl.Optional != nil && *serviceRefDecl.Optional) { - continue - } - return fmt.Errorf("service-ref for %s is not defined", serviceRefDecl.Name) - } - - var ( - namespace = synthesizedComp.Namespace - sd *appsv1.ServiceDescriptor - err error - ) - switch { - case serviceRef.Cluster != "": - sd, err = handleServiceRefFromCluster(ctx, cli, namespace, *serviceRef, serviceRefDecl, true) - case serviceRef.ClusterServiceSelector != nil: - sd, err = handleServiceRefFromCluster(ctx, cli, namespace, *serviceRef, serviceRefDecl, false) - case serviceRef.ServiceDescriptor != "": - sd, err = handleServiceRefFromServiceDescriptor(ctx, cli, namespace, *serviceRef, serviceRefDecl) - } - if err != nil { - return err - } - serviceReferences[serviceRefDecl.Name] = sd - } - - if len(serviceReferences) > 0 { - synthesizedComp.ServiceReferences = serviceReferences - } - return nil -} - -func handleServiceRefFromCluster(ctx context.Context, cli client.Reader, namespace string, - serviceRef appsv1.ServiceRef, serviceRefDecl appsv1.ServiceRefDeclaration, legacy bool) (*appsv1.ServiceDescriptor, error) { - resolver := referencedVars - if legacy { - resolver = referencedVars4Legacy - } - vars, err := resolver(ctx, cli, namespace, serviceRef) - if err != nil { - return nil, err - } - - // just in-memory service descriptor object, the namespace and name are trivial - b := builder.NewServiceDescriptorBuilder(namespace, serviceRefDecl.Name). - SetServiceVersion(""). - SetServiceKind("") - for i, s := range []func(appsv1.CredentialVar) *builder.ServiceDescriptorBuilder{b.SetEndpoint, b.SetHost, b.SetPort, b.SetAuthUsername, b.SetAuthPassword} { - if vars[i] != nil { - s(*vars[i]) - } - } - return b.GetObject(), nil -} - -func referencedVars(ctx context.Context, cli client.Reader, namespace string, serviceRef appsv1.ServiceRef) ([]*appsv1.CredentialVar, error) { - var ( - vars = []*appsv1.CredentialVar{nil, nil, nil, nil, nil} - err error - ) - vars[0], vars[1], vars[2], err = referencedServiceVars(ctx, cli, namespace, serviceRef) - if err != nil { - return nil, err - } - vars[3], vars[4], err = referencedCredentialVars(ctx, cli, namespace, serviceRef) - if err != nil { - return nil, err - } - return vars, nil -} - -func referencedServiceVars(ctx context.Context, cli client.Reader, namespace string, - serviceRef appsv1.ServiceRef) (*appsv1.CredentialVar, *appsv1.CredentialVar, *appsv1.CredentialVar, error) { - var ( - selector = serviceRef.ClusterServiceSelector - host, port *appsv1.CredentialVar - obj any - err error - ) - - if selector.Service == nil { - return nil, nil, nil, nil - } - - if serviceRef.Namespace != "" { - namespace = serviceRef.Namespace - } - switch { - case len(selector.Service.Component) == 0: - obj, err = clusterServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Service) - case selector.Service.Service == "headless": - obj, err = headlessCompServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Component) - default: - obj, err = compServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Component, selector.Service.Service) - } - if err != nil { - return nil, nil, nil, err - } - - host = &appsv1.CredentialVar{Value: composeHostValueFromServices(obj)} - if p := composePortValueFromServices(obj, selector.Service.Port); p != nil { - port = &appsv1.CredentialVar{Value: *p} - } - - endpoint := func() *appsv1.CredentialVar { - hval := host.Value - if port == nil { - return &appsv1.CredentialVar{Value: hval} - } - if strings.Contains(hval, ",") { - // pod-service, the port value has format: host1:port1,host2,port2,... - return &appsv1.CredentialVar{Value: port.Value} - } - return &appsv1.CredentialVar{Value: fmt.Sprintf("%s:%s", hval, port.Value)} - } - return endpoint(), host, port, nil -} - -func referencedCredentialVars(ctx context.Context, cli client.Reader, namespace string, - serviceRef appsv1.ServiceRef) (*appsv1.CredentialVar, *appsv1.CredentialVar, error) { - var ( - selector = serviceRef.ClusterServiceSelector - vars = []*appsv1.CredentialVar{nil, nil} - ) - - if selector.Credential == nil { - return nil, nil, nil - } - - secretKey := types.NamespacedName{ - Namespace: namespace, - Name: constant.GenerateAccountSecretName(selector.Cluster, selector.Credential.Component, selector.Credential.Name), - } - if serviceRef.Namespace != "" { - secretKey.Namespace = serviceRef.Namespace - } - secret := &corev1.Secret{} - if err := cli.Get(ctx, secretKey, secret); err != nil { - return nil, nil, err - } - - for idx, key := range []string{constant.AccountNameForSecret, constant.AccountPasswdForSecret} { - if _, ok := secret.Data[key]; ok { - if secret.Namespace == namespace { - vars[idx] = &appsv1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secret.Name}, - Key: key, - }, - }, - } - } else { - vars[idx] = &appsv1.CredentialVar{ - Value: string(secret.Data[key]), - } - } - } - } - return vars[0], vars[1], nil -} - -func referencedVars4Legacy(ctx context.Context, cli client.Reader, namespace string, serviceRef appsv1.ServiceRef) ([]*appsv1.CredentialVar, error) { - secret := &corev1.Secret{} - secretKey := types.NamespacedName{ - Namespace: func() string { - if serviceRef.Namespace != "" { - return serviceRef.Namespace - } - return namespace - }(), - // keep this to reference a legacy cluster - Name: fmt.Sprintf("%s-conn-credential", serviceRef.Cluster), - } - if err := cli.Get(ctx, secretKey, secret); err != nil { - return nil, err - } - - vars := []*appsv1.CredentialVar{nil, nil, nil, nil, nil} - keys := []string{ - constant.ServiceDescriptorEndpointKey, - constant.ServiceDescriptorHostKey, - constant.ServiceDescriptorPortKey, - constant.ServiceDescriptorUsernameKey, - constant.ServiceDescriptorPasswordKey, - } - for idx, key := range keys { - if key == constant.ServiceDescriptorHostKey { - // don't set the host for legacy clusters - continue - } - if _, ok := secret.Data[key]; ok { - vars[idx] = &appsv1.CredentialVar{ - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: secret.Name}, - Key: key, - }, - }, - } - } - } - return vars, nil -} - -// handleServiceRefFromServiceDescriptor handles the service reference is provided by external ServiceDescriptor object. -func handleServiceRefFromServiceDescriptor(ctx context.Context, cli client.Reader, namespace string, - serviceRef appsv1.ServiceRef, serviceRefDecl appsv1.ServiceRefDeclaration) (*appsv1.ServiceDescriptor, error) { - // verify service kind and version - verifyServiceKindAndVersion := func(serviceDescriptor appsv1.ServiceDescriptor, _ ...appsv1.ServiceRefDeclarationSpec) bool { - for _, serviceRefDeclSpec := range serviceRefDecl.ServiceRefDeclarationSpecs { - if getWellKnownServiceKindAliasMapping(serviceRefDeclSpec.ServiceKind) != getWellKnownServiceKindAliasMapping(serviceDescriptor.Spec.ServiceKind) { - continue - } - versionMatch := verifyServiceVersion(serviceDescriptor.Spec.ServiceVersion, serviceRefDeclSpec.ServiceVersion) - if versionMatch { - return true - } - } - return false - } - - if len(serviceRef.Namespace) > 0 { - namespace = serviceRef.Namespace - } - serviceDescriptorKey := client.ObjectKey{ - Namespace: namespace, - Name: serviceRef.ServiceDescriptor, - } - serviceDescriptor := &appsv1.ServiceDescriptor{} - if err := cli.Get(ctx, serviceDescriptorKey, serviceDescriptor); err != nil { - return nil, err - } - if serviceDescriptor.Status.Phase != appsv1.AvailablePhase { - return nil, fmt.Errorf("service descriptor %s status is not available", serviceDescriptor.Name) - } - - match := verifyServiceKindAndVersion(*serviceDescriptor, serviceRefDecl.ServiceRefDeclarationSpecs...) - if !match { - return nil, fmt.Errorf("service descriptor %s kind or version is not match with service reference declaration %s", serviceDescriptor.Name, serviceRefDecl.Name) - } - return serviceDescriptor, nil -} - -func verifyServiceVersion(serviceDescriptorVersion, serviceRefDeclarationServiceVersion string) bool { - isRegex := false - regex, err := regexp.Compile(serviceRefDeclarationServiceVersion) - if err == nil { - isRegex = true - } - if !isRegex { - return serviceDescriptorVersion == serviceRefDeclarationServiceVersion - } - return regex.MatchString(serviceDescriptorVersion) -} - -func getWellKnownServiceKindAliasMapping(serviceKind string) string { - lowerServiceKind := strings.ToLower(serviceKind) - switch { - case slices.Contains(constant.GetZookeeperAlias(), lowerServiceKind): - return constant.ServiceKindZookeeper - case slices.Contains(constant.GetElasticSearchAlias(), lowerServiceKind): - return constant.ServiceKindElasticSearch - case slices.Contains(constant.GetMongoDBAlias(), lowerServiceKind): - return constant.ServiceKindMongoDB - case slices.Contains(constant.GetPostgreSQLAlias(), lowerServiceKind): - return constant.ServiceKindPostgreSQL - case slices.Contains(constant.GetClickHouseAlias(), lowerServiceKind): - return constant.ServiceKindClickHouse - default: - return lowerServiceKind - } -} diff --git a/pkg/controller/component/service_reference.go b/pkg/controller/component/service_reference.go index c1c945e6978..ddce39756bc 100644 --- a/pkg/controller/component/service_reference.go +++ b/pkg/controller/component/service_reference.go @@ -21,14 +21,316 @@ package component import ( "context" + "fmt" + "regexp" + "strings" + "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" + "github.com/apecloud/kubeblocks/pkg/constant" + "github.com/apecloud/kubeblocks/pkg/controller/builder" ) +func buildServiceReferences(ctx context.Context, cli client.Reader, + synthesizedComp *SynthesizedComponent, compDef *appsv1.ComponentDefinition, comp *appsv1.Component) error { + if err := buildServiceReferencesWithoutResolve(ctx, cli, synthesizedComp, compDef, comp); err != nil { + return err + } + return resolveServiceReferences(ctx, cli, synthesizedComp) +} + +func buildServiceReferencesWithoutResolve(ctx context.Context, cli client.Reader, + synthesizedComp *SynthesizedComponent, compDef *appsv1.ComponentDefinition, comp *appsv1.Component) error { + if compDef == nil || comp == nil || len(compDef.Spec.ServiceRefDeclarations) == 0 { + return nil + } + + serviceRefs := map[string]*appsv1.ServiceRef{} + for i, serviceRef := range comp.Spec.ServiceRefs { + serviceRefs[serviceRef.Name] = &comp.Spec.ServiceRefs[i] + } + + serviceReferences := make(map[string]*appsv1.ServiceDescriptor, len(compDef.Spec.ServiceRefDeclarations)) + for _, serviceRefDecl := range compDef.Spec.ServiceRefDeclarations { + serviceRef, ok := serviceRefs[serviceRefDecl.Name] + if !ok { + if serviceRefDecl.Optional != nil && *serviceRefDecl.Optional { + continue + } + return fmt.Errorf("service-ref for %s is not defined", serviceRefDecl.Name) + } + + var ( + namespace = synthesizedComp.Namespace + sd *appsv1.ServiceDescriptor + err error + ) + switch { + case serviceRef.Cluster != "": + sd, err = handleServiceRefFromCluster(ctx, cli, namespace, *serviceRef, serviceRefDecl, true) + case serviceRef.ClusterServiceSelector != nil: + sd, err = handleServiceRefFromCluster(ctx, cli, namespace, *serviceRef, serviceRefDecl, false) + case serviceRef.ServiceDescriptor != "": + sd, err = handleServiceRefFromServiceDescriptor(ctx, cli, namespace, *serviceRef, serviceRefDecl) + } + if err != nil { + return err + } + serviceReferences[serviceRefDecl.Name] = sd + } + + if len(serviceReferences) > 0 { + synthesizedComp.ServiceReferences = serviceReferences + } + return nil +} + +func handleServiceRefFromCluster(ctx context.Context, cli client.Reader, namespace string, + serviceRef appsv1.ServiceRef, serviceRefDecl appsv1.ServiceRefDeclaration, legacy bool) (*appsv1.ServiceDescriptor, error) { + resolver := referencedVars + if legacy { + resolver = referencedVars4Legacy + } + vars, err := resolver(ctx, cli, namespace, serviceRef) + if err != nil { + return nil, err + } + + // just in-memory service descriptor object, the namespace and name are trivial + b := builder.NewServiceDescriptorBuilder(namespace, serviceRefDecl.Name). + SetServiceVersion(""). + SetServiceKind("") + for i, s := range []func(appsv1.CredentialVar) *builder.ServiceDescriptorBuilder{b.SetEndpoint, b.SetHost, b.SetPort, b.SetAuthUsername, b.SetAuthPassword} { + if vars[i] != nil { + s(*vars[i]) + } + } + return b.GetObject(), nil +} + +func referencedVars(ctx context.Context, cli client.Reader, namespace string, serviceRef appsv1.ServiceRef) ([]*appsv1.CredentialVar, error) { + var ( + vars = []*appsv1.CredentialVar{nil, nil, nil, nil, nil} + err error + ) + vars[0], vars[1], vars[2], err = referencedServiceVars(ctx, cli, namespace, serviceRef) + if err != nil { + return nil, err + } + vars[3], vars[4], err = referencedCredentialVars(ctx, cli, namespace, serviceRef) + if err != nil { + return nil, err + } + return vars, nil +} + +func referencedServiceVars(ctx context.Context, cli client.Reader, namespace string, + serviceRef appsv1.ServiceRef) (*appsv1.CredentialVar, *appsv1.CredentialVar, *appsv1.CredentialVar, error) { + var ( + selector = serviceRef.ClusterServiceSelector + host, port *appsv1.CredentialVar + obj any + err error + ) + + if selector.Service == nil { + return nil, nil, nil, nil + } + + if serviceRef.Namespace != "" { + namespace = serviceRef.Namespace + } + switch { + case len(selector.Service.Component) == 0: + obj, err = clusterServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Service) + case selector.Service.Service == "headless": + obj, err = headlessCompServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Component) + default: + obj, err = compServiceGetter(ctx, cli, namespace, selector.Cluster, selector.Service.Component, selector.Service.Service) + } + if err != nil { + return nil, nil, nil, err + } + + host = &appsv1.CredentialVar{Value: composeHostValueFromServices(obj)} + if p := composePortValueFromServices(obj, selector.Service.Port); p != nil { + port = &appsv1.CredentialVar{Value: *p} + } + + endpoint := func() *appsv1.CredentialVar { + hval := host.Value + if port == nil { + return &appsv1.CredentialVar{Value: hval} + } + if strings.Contains(hval, ",") { + // pod-service, the port value has format: host1:port1,host2,port2,... + return &appsv1.CredentialVar{Value: port.Value} + } + return &appsv1.CredentialVar{Value: fmt.Sprintf("%s:%s", hval, port.Value)} + } + return endpoint(), host, port, nil +} + +func referencedCredentialVars(ctx context.Context, cli client.Reader, namespace string, + serviceRef appsv1.ServiceRef) (*appsv1.CredentialVar, *appsv1.CredentialVar, error) { + var ( + selector = serviceRef.ClusterServiceSelector + vars = []*appsv1.CredentialVar{nil, nil} + ) + + if selector.Credential == nil { + return nil, nil, nil + } + + secretKey := types.NamespacedName{ + Namespace: namespace, + Name: constant.GenerateAccountSecretName(selector.Cluster, selector.Credential.Component, selector.Credential.Name), + } + if serviceRef.Namespace != "" { + secretKey.Namespace = serviceRef.Namespace + } + secret := &corev1.Secret{} + if err := cli.Get(ctx, secretKey, secret); err != nil { + return nil, nil, err + } + + for idx, key := range []string{constant.AccountNameForSecret, constant.AccountPasswdForSecret} { + if _, ok := secret.Data[key]; ok { + if secret.Namespace == namespace { + vars[idx] = &appsv1.CredentialVar{ + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: secret.Name}, + Key: key, + }, + }, + } + } else { + vars[idx] = &appsv1.CredentialVar{ + Value: string(secret.Data[key]), + } + } + } + } + return vars[0], vars[1], nil +} + +func referencedVars4Legacy(ctx context.Context, cli client.Reader, namespace string, serviceRef appsv1.ServiceRef) ([]*appsv1.CredentialVar, error) { + secret := &corev1.Secret{} + secretKey := types.NamespacedName{ + Namespace: func() string { + if serviceRef.Namespace != "" { + return serviceRef.Namespace + } + return namespace + }(), + // keep this to reference a legacy cluster + Name: fmt.Sprintf("%s-conn-credential", serviceRef.Cluster), + } + if err := cli.Get(ctx, secretKey, secret); err != nil { + return nil, err + } + + vars := []*appsv1.CredentialVar{nil, nil, nil, nil, nil} + keys := []string{ + constant.ServiceDescriptorEndpointKey, + constant.ServiceDescriptorHostKey, + constant.ServiceDescriptorPortKey, + constant.ServiceDescriptorUsernameKey, + constant.ServiceDescriptorPasswordKey, + } + for idx, key := range keys { + if key == constant.ServiceDescriptorHostKey { + // don't set the host for legacy clusters + continue + } + if _, ok := secret.Data[key]; ok { + vars[idx] = &appsv1.CredentialVar{ + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: secret.Name}, + Key: key, + }, + }, + } + } + } + return vars, nil +} + +// handleServiceRefFromServiceDescriptor handles the service reference is provided by external ServiceDescriptor object. +func handleServiceRefFromServiceDescriptor(ctx context.Context, cli client.Reader, namespace string, + serviceRef appsv1.ServiceRef, serviceRefDecl appsv1.ServiceRefDeclaration) (*appsv1.ServiceDescriptor, error) { + // verify service kind and version + verifyServiceKindAndVersion := func(serviceDescriptor appsv1.ServiceDescriptor, _ ...appsv1.ServiceRefDeclarationSpec) bool { + for _, serviceRefDeclSpec := range serviceRefDecl.ServiceRefDeclarationSpecs { + if getWellKnownServiceKindAliasMapping(serviceRefDeclSpec.ServiceKind) != getWellKnownServiceKindAliasMapping(serviceDescriptor.Spec.ServiceKind) { + continue + } + versionMatch := verifyServiceVersion(serviceDescriptor.Spec.ServiceVersion, serviceRefDeclSpec.ServiceVersion) + if versionMatch { + return true + } + } + return false + } + + if len(serviceRef.Namespace) > 0 { + namespace = serviceRef.Namespace + } + serviceDescriptorKey := client.ObjectKey{ + Namespace: namespace, + Name: serviceRef.ServiceDescriptor, + } + serviceDescriptor := &appsv1.ServiceDescriptor{} + if err := cli.Get(ctx, serviceDescriptorKey, serviceDescriptor); err != nil { + return nil, err + } + if serviceDescriptor.Status.Phase != appsv1.AvailablePhase { + return nil, fmt.Errorf("service descriptor %s status is not available", serviceDescriptor.Name) + } + + match := verifyServiceKindAndVersion(*serviceDescriptor, serviceRefDecl.ServiceRefDeclarationSpecs...) + if !match { + return nil, fmt.Errorf("service descriptor %s kind or version is not match with service reference declaration %s", serviceDescriptor.Name, serviceRefDecl.Name) + } + return serviceDescriptor, nil +} + +func getWellKnownServiceKindAliasMapping(serviceKind string) string { + lowerServiceKind := strings.ToLower(serviceKind) + switch { + case slices.Contains(constant.GetZookeeperAlias(), lowerServiceKind): + return constant.ServiceKindZookeeper + case slices.Contains(constant.GetElasticSearchAlias(), lowerServiceKind): + return constant.ServiceKindElasticSearch + case slices.Contains(constant.GetMongoDBAlias(), lowerServiceKind): + return constant.ServiceKindMongoDB + case slices.Contains(constant.GetPostgreSQLAlias(), lowerServiceKind): + return constant.ServiceKindPostgreSQL + case slices.Contains(constant.GetClickHouseAlias(), lowerServiceKind): + return constant.ServiceKindClickHouse + default: + return lowerServiceKind + } +} + +func verifyServiceVersion(serviceDescriptorVersion, serviceRefDeclarationServiceVersion string) bool { + isRegex := false + regex, err := regexp.Compile(serviceRefDeclarationServiceVersion) + if err == nil { + isRegex = true + } + if !isRegex { + return serviceDescriptorVersion == serviceRefDeclarationServiceVersion + } + return regex.MatchString(serviceDescriptorVersion) +} + func resolveServiceReferences(ctx context.Context, cli client.Reader, synthesizedComp *SynthesizedComponent) error { for _, serviceDescriptor := range synthesizedComp.ServiceReferences { if serviceDescriptor == nil { diff --git a/pkg/controller/component/service_descriptor_utils_test.go b/pkg/controller/component/service_reference_test.go similarity index 98% rename from pkg/controller/component/service_descriptor_utils_test.go rename to pkg/controller/component/service_reference_test.go index 23194435164..1f0a951fe6d 100644 --- a/pkg/controller/component/service_descriptor_utils_test.go +++ b/pkg/controller/component/service_reference_test.go @@ -36,7 +36,7 @@ import ( testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) -var _ = Describe("build service references", func() { +var _ = Describe("service references", func() { cleanEnv := func() { // must wait till resources deleted and no longer existed before the testcases start, // otherwise if later it needs to create some new resource objects with the same name, @@ -184,13 +184,8 @@ var _ = Describe("build service references", func() { }) It("has service-ref not defined", func() { - // for generated components, undefined service-refs are ignored by default. - err := buildServiceReferencesWithoutResolve(testCtx.Ctx, testCtx.Cli, synthesizedComp, compDef, comp) - Expect(err).Should(Succeed()) - Expect(synthesizedComp.ServiceReferences).Should(HaveLen(0)) - comp.Spec.CompDef = compDef.GetName() - err = buildServiceReferencesWithoutResolve(testCtx.Ctx, testCtx.Cli, synthesizedComp, compDef, comp) + err := buildServiceReferencesWithoutResolve(testCtx.Ctx, testCtx.Cli, synthesizedComp, compDef, comp) Expect(err).ShouldNot(Succeed()) Expect(err.Error()).Should(ContainSubstring("service-ref for %s is not defined", serviceRefDeclaration.Name)) diff --git a/pkg/controller/component/synthesize_component.go b/pkg/controller/component/synthesize_component.go index 6599339e65f..bfda2b8e1fa 100644 --- a/pkg/controller/component/synthesize_component.go +++ b/pkg/controller/component/synthesize_component.go @@ -24,6 +24,7 @@ import ( "fmt" "strconv" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -41,66 +42,9 @@ var ( ) // BuildSynthesizedComponent builds a new SynthesizedComponent object, which is a mixture of component-related configs from ComponentDefinition and Component. -func BuildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, - cli client.Reader, - cluster *appsv1.Cluster, - compDef *appsv1.ComponentDefinition, - comp *appsv1.Component) (*SynthesizedComponent, error) { - return buildSynthesizedComponent(reqCtx, cli, compDef, comp, cluster, nil) -} - -// BuildSynthesizedComponent4Generated builds SynthesizedComponent for generated Component which w/o ComponentDefinition. -func BuildSynthesizedComponent4Generated(reqCtx intctrlutil.RequestCtx, - cli client.Reader, - cluster *appsv1.Cluster, - comp *appsv1.Component) (*appsv1.ComponentDefinition, *SynthesizedComponent, error) { - clusterCompSpec, err := getClusterCompSpec4Component(reqCtx.Ctx, cli, cluster, comp) - if err != nil { - return nil, nil, err - } - if clusterCompSpec == nil { - return nil, nil, fmt.Errorf("cluster component spec is not found: %s", comp.Name) - } - compDef, err := getComponentDefinition(reqCtx.Ctx, cli, clusterCompSpec) - if err != nil { - return nil, nil, err - } - synthesizedComp, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, cluster, clusterCompSpec) - if err != nil { - return nil, nil, err - } - return compDef, synthesizedComp, nil -} - -// BuildSynthesizedComponentWrapper builds a new SynthesizedComponent object with a given ClusterComponentSpec. -// TODO: remove this -func BuildSynthesizedComponentWrapper(reqCtx intctrlutil.RequestCtx, - cli client.Reader, - cluster *appsv1.Cluster, - clusterCompSpec *appsv1.ClusterComponentSpec) (*SynthesizedComponent, error) { - if clusterCompSpec == nil { - return nil, fmt.Errorf("cluster component spec is not provided") - } - compDef, err := getComponentDefinition(reqCtx.Ctx, cli, clusterCompSpec) - if err != nil { - return nil, err - } - comp, err := BuildComponent(cluster, clusterCompSpec, nil, nil) - if err != nil { - return nil, err - } - return buildSynthesizedComponent(reqCtx, cli, compDef, comp, cluster, clusterCompSpec) -} - -// buildSynthesizedComponent builds a new SynthesizedComponent object, which is a mixture of component-related configs from ComponentDefinition and Component. -// !!! Do not use @clusterDef, @cluster and @clusterCompSpec since they are used for the backward compatibility only. -// TODO: remove @reqCtx & @cli -func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, - cli client.Reader, - compDef *appsv1.ComponentDefinition, - comp *appsv1.Component, - cluster *appsv1.Cluster, - clusterCompSpec *appsv1.ClusterComponentSpec) (*SynthesizedComponent, error) { +// TODO: remove @ctx & @cli +func BuildSynthesizedComponent(ctx context.Context, cli client.Reader, + compDef *appsv1.ComponentDefinition, comp *appsv1.Component, cluster *appsv1.Cluster) (*SynthesizedComponent, error) { if compDef == nil || comp == nil { return nil, nil } @@ -117,7 +61,7 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, if err != nil { return nil, err } - comp2CompDef, err := buildComp2CompDefs(reqCtx.Ctx, cli, cluster, clusterCompSpec) + comp2CompDef, err := buildComp2CompDefs(ctx, cli, cluster) if err != nil { return nil, err } @@ -197,13 +141,11 @@ func buildSynthesizedComponent(reqCtx intctrlutil.RequestCtx, buildRuntimeClassName(synthesizeComp, comp) if err = buildKBAgentContainer(synthesizeComp); err != nil { - reqCtx.Log.Error(err, "build kb-agent container failed") - return nil, err + return nil, errors.Wrap(err, "build kb-agent container failed") } - if err = buildServiceReferences(reqCtx.Ctx, cli, synthesizeComp, compDef, comp); err != nil { - reqCtx.Log.Error(err, "build service references failed.") - return nil, err + if err = buildServiceReferences(ctx, cli, synthesizeComp, compDef, comp); err != nil { + return nil, errors.Wrap(err, "build service references failed") } return synthesizeComp, nil @@ -219,26 +161,20 @@ func clusterGeneration(cluster *appsv1.Cluster, comp *appsv1.Component) string { return strconv.FormatInt(cluster.Generation, 10) } -func buildComp2CompDefs(ctx context.Context, cli client.Reader, cluster *appsv1.Cluster, clusterCompSpec *appsv1.ClusterComponentSpec) (map[string]string, error) { +func buildComp2CompDefs(ctx context.Context, cli client.Reader, cluster *appsv1.Cluster) (map[string]string, error) { if cluster == nil { return nil, nil } mapping := make(map[string]string) - // Build from ComponentSpecs - if len(cluster.Spec.ComponentSpecs) == 0 { - if clusterCompSpec != nil && len(clusterCompSpec.ComponentDef) > 0 { - mapping[clusterCompSpec.Name] = clusterCompSpec.ComponentDef - } - } else { - for _, comp := range cluster.Spec.ComponentSpecs { - if len(comp.ComponentDef) > 0 { - mapping[comp.Name] = comp.ComponentDef - } + // build from componentSpecs + for _, comp := range cluster.Spec.ComponentSpecs { + if len(comp.ComponentDef) > 0 { + mapping[comp.Name] = comp.ComponentDef } } - // Build from ShardingSpecs + // build from shardingSpecs for _, shardingSpec := range cluster.Spec.ShardingSpecs { shardingComps, err := intctrlutil.ListShardingComponents(ctx, cli, cluster, shardingSpec.Name) if err != nil { diff --git a/pkg/controller/component/synthesize_component_test.go b/pkg/controller/component/synthesize_component_test.go index ce9acd44a71..aa945d77db0 100644 --- a/pkg/controller/component/synthesize_component_test.go +++ b/pkg/controller/component/synthesize_component_test.go @@ -29,15 +29,10 @@ import ( appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" "github.com/apecloud/kubeblocks/pkg/constant" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" ) var _ = Describe("synthesized component", func() { var ( - reqCtx = intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Log: logger, - } cli client.Reader compDef *appsv1.ComponentDefinition comp *appsv1.Component @@ -110,7 +105,7 @@ var _ = Describe("synthesized component", func() { }) It("comp def", func() { - synthesizedComp, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + synthesizedComp, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).Should(BeNil()) Expect(synthesizedComp).ShouldNot(BeNil()) @@ -128,7 +123,7 @@ var _ = Describe("synthesized component", func() { }, }, }) - synthesizedComp, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + synthesizedComp, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).Should(BeNil()) Expect(synthesizedComp).ShouldNot(BeNil()) @@ -150,7 +145,7 @@ var _ = Describe("synthesized component", func() { }, }, }) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("not defined in definition")) }) @@ -167,7 +162,7 @@ var _ = Describe("synthesized component", func() { }, }, }) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("partial overriding is not supported")) }) @@ -177,7 +172,7 @@ var _ = Describe("synthesized component", func() { Name: func() *string { name := "external"; return &name }(), ClusterComponentConfigSource: appsv1.ClusterComponentConfigSource{}, }) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("there is no content provided for config template")) }) @@ -230,13 +225,13 @@ var _ = Describe("synthesized component", func() { It("duplicated", func() { comp.Spec.Env = append(comp.Spec.Env, comp.Spec.Env[0]) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("duplicated user-defined env var")) }) It("ok", func() { - synthesizedComp, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + synthesizedComp, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).Should(BeNil()) Expect(synthesizedComp).ShouldNot(BeNil()) Expect(synthesizedComp.PodSpec.Containers[0].Env).Should(HaveLen(2)) @@ -309,7 +304,7 @@ var _ = Describe("synthesized component", func() { It("duplicated", func() { comp.Spec.Volumes = append(comp.Spec.Volumes, comp.Spec.Volumes[0]) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("duplicated volume")) }) @@ -317,22 +312,13 @@ var _ = Describe("synthesized component", func() { It("duplicated with definition", func() { comp.Spec.Volumes = append(comp.Spec.Volumes, compDef.Spec.Runtime.Volumes[0]) - _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + _, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).ShouldNot(BeNil()) Expect(err.Error()).Should(ContainSubstring("duplicated volume")) }) - // It("missed volumes", func() { - // volumes := comp.Spec.Volumes - // comp.Spec.Volumes = comp.Spec.Volumes[0:1] - // - // _, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) - // Expect(err).ShouldNot(BeNil()) - // Expect(err.Error()).Should(And(ContainSubstring("volumes should be provided for mounts"), ContainSubstring(volumes[1].Name))) - // }) - It("ok", func() { - synthesizedComp, err := buildSynthesizedComponent(reqCtx, cli, compDef, comp, nil, nil) + synthesizedComp, err := BuildSynthesizedComponent(ctx, cli, compDef, comp, nil) Expect(err).Should(BeNil()) Expect(synthesizedComp).ShouldNot(BeNil()) Expect(synthesizedComp.PodSpec.Volumes).Should(HaveLen(4)) diff --git a/pkg/controller/component/vars.go b/pkg/controller/component/vars.go index 7b86b4689ed..449e11cef3d 100644 --- a/pkg/controller/component/vars.go +++ b/pkg/controller/component/vars.go @@ -61,11 +61,7 @@ func VarReferenceRegExp() *regexp.Regexp { // ResolveTemplateNEnvVars resolves all built-in and user-defined vars for config template and Env usage. func ResolveTemplateNEnvVars(ctx context.Context, cli client.Reader, synthesizedComp *SynthesizedComponent, definedVars []appsv1.EnvVar) (map[string]any, []corev1.EnvVar, error) { - return resolveTemplateNEnvVars(ctx, cli, synthesizedComp, definedVars, false) -} - -func ResolveEnvVars4LegacyCluster(ctx context.Context, cli client.Reader, synthesizedComp *SynthesizedComponent, definedVars []appsv1.EnvVar) (map[string]any, []corev1.EnvVar, error) { - return resolveTemplateNEnvVars(ctx, cli, synthesizedComp, definedVars, true) + return resolveTemplateNEnvVars(ctx, cli, synthesizedComp, definedVars) } func InjectEnvVars(synthesizedComp *SynthesizedComponent, envVars []corev1.EnvVar, envFromSources []corev1.EnvFromSource) { @@ -104,23 +100,19 @@ func InjectEnvVars4Containers(synthesizedComp *SynthesizedComponent, envVars []c } func resolveTemplateNEnvVars(ctx context.Context, cli client.Reader, synthesizedComp *SynthesizedComponent, - definedVars []appsv1.EnvVar, legacy bool) (map[string]any, []corev1.EnvVar, error) { + definedVars []appsv1.EnvVar) (map[string]any, []corev1.EnvVar, error) { templateVars, envVars, err := resolveNewTemplateNEnvVars(ctx, cli, synthesizedComp, definedVars) if err != nil { return nil, nil, err } - implicitEnvVars, err := buildLegacyImplicitEnvVars(synthesizedComp, legacy) + implicitEnvVars, err := buildLegacyImplicitEnvVars(synthesizedComp) if err != nil { return nil, nil, err } - if legacy { - envVars = implicitEnvVars - } else { - // TODO: duplicated - envVars = append(envVars, implicitEnvVars...) - } + // TODO: duplicated + envVars = append(envVars, implicitEnvVars...) formattedTemplateVars := func() map[string]any { vars := make(map[string]any) @@ -142,9 +134,9 @@ func resolveNewTemplateNEnvVars(ctx context.Context, cli client.Reader, synthesi return templateVars, append(envVars, credentialVars...), nil } -func buildLegacyImplicitEnvVars(synthesizedComp *SynthesizedComponent, legacy bool) ([]corev1.EnvVar, error) { +func buildLegacyImplicitEnvVars(synthesizedComp *SynthesizedComponent) ([]corev1.EnvVar, error) { envVars := make([]corev1.EnvVar, 0) - envVars = append(envVars, buildDefaultEnvVars(synthesizedComp, legacy)...) + envVars = append(envVars, buildDefaultEnvVars(synthesizedComp)...) envVars = append(envVars, buildEnv4TLS(synthesizedComp)...) userDefinedVars, err := buildEnv4UserDefined(synthesizedComp.Annotations) if err != nil { @@ -305,7 +297,7 @@ func resolveValueReferenceNEscaping(templateVars, credentialVars map[string]core return v1, v2 } -func buildDefaultEnvVars(synthesizedComp *SynthesizedComponent, legacy bool) []corev1.EnvVar { +func buildDefaultEnvVars(synthesizedComp *SynthesizedComponent) []corev1.EnvVar { vars := make([]corev1.EnvVar, 0) // can not use map, it is unordered namedFields := []struct { @@ -339,19 +331,10 @@ func buildDefaultEnvVars(synthesizedComp *SynthesizedComponent, legacy bool) []c clusterCompName := func() string { return constant.GenerateClusterComponentName(synthesizedComp.ClusterName, synthesizedComp.Name) }() - if legacy { - vars = append(vars, []corev1.EnvVar{ - {Name: constant.KBEnvClusterName, Value: synthesizedComp.ClusterName}, - {Name: constant.KBEnvCompName, Value: synthesizedComp.Name}, - {Name: constant.KBEnvClusterCompName, Value: clusterCompName}, - {Name: constant.KBEnvClusterUIDPostfix8Deprecated, Value: clusterUIDPostfix(synthesizedComp)}, - {Name: constant.KBEnvPodFQDN, Value: fmt.Sprintf("%s.%s-headless.%s.svc", constant.EnvPlaceHolder(constant.KBEnvPodName), constant.EnvPlaceHolder(constant.KBEnvClusterCompName), constant.EnvPlaceHolder(constant.KBEnvNamespace))}}...) - } else { - vars = append(vars, corev1.EnvVar{ - Name: constant.KBEnvPodFQDN, - Value: fmt.Sprintf("%s.%s-headless.%s.svc", constant.EnvPlaceHolder(constant.KBEnvPodName), clusterCompName, constant.EnvPlaceHolder(constant.KBEnvNamespace)), - }) - } + vars = append(vars, corev1.EnvVar{ + Name: constant.KBEnvPodFQDN, + Value: fmt.Sprintf("%s.%s-headless.%s.svc", constant.EnvPlaceHolder(constant.KBEnvPodName), clusterCompName, constant.EnvPlaceHolder(constant.KBEnvNamespace)), + }) return vars } diff --git a/pkg/controller/component/vars_test.go b/pkg/controller/component/vars_test.go index 1d65f2316f9..fed30d94529 100644 --- a/pkg/controller/component/vars_test.go +++ b/pkg/controller/component/vars_test.go @@ -181,7 +181,7 @@ var _ = Describe("vars", func() { By("check default env vars") targetEnvVars := builtinTemplateVars(synthesizedComp, nil) - targetEnvVars = append(targetEnvVars, buildDefaultEnvVars(synthesizedComp, false)...) + targetEnvVars = append(targetEnvVars, buildDefaultEnvVars(synthesizedComp)...) checkEnvVars(envVars, targetEnvVars) }) diff --git a/pkg/controller/configuration/configuration_test.go b/pkg/controller/configuration/configuration_test.go index f561ee3703c..1c05206f803 100644 --- a/pkg/controller/configuration/configuration_test.go +++ b/pkg/controller/configuration/configuration_test.go @@ -30,7 +30,6 @@ import ( appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" "github.com/apecloud/kubeblocks/pkg/controller/component" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -79,15 +78,11 @@ func newAllFieldsClusterObj(compDef *appsv1.ComponentDefinition, create bool) (* } func newAllFieldsSynthesizedComponent(compDef *appsv1.ComponentDefinition, cluster *appsv1.Cluster) *component.SynthesizedComponent { - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Log: logger, - } comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) if err != nil { panic(fmt.Sprintf("build component object error: %v", err)) } - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(testCtx.Ctx, testCtx.Cli, compDef, comp, cluster) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) addTestVolumeMount(synthesizeComp.PodSpec, mysqlCompName) diff --git a/pkg/controller/configuration/envfrom_utils_test.go b/pkg/controller/configuration/envfrom_utils_test.go index b53a97dbd9f..4c51f1b322d 100644 --- a/pkg/controller/configuration/envfrom_utils_test.go +++ b/pkg/controller/configuration/envfrom_utils_test.go @@ -31,7 +31,6 @@ import ( "github.com/apecloud/kubeblocks/pkg/configuration/core" cfgutil "github.com/apecloud/kubeblocks/pkg/configuration/util" "github.com/apecloud/kubeblocks/pkg/controller/component" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" testutil "github.com/apecloud/kubeblocks/pkg/testutil/k8s" ) @@ -82,14 +81,10 @@ var _ = Describe("ConfigEnvFrom test", func() { Context("test config template inject envfrom", func() { It("should inject success", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) Expect(err).Should(Succeed()) - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(ctx, testCtx.Cli, compDef, comp, cluster) Expect(err).Should(Succeed()) podSpec := &corev1.PodSpec{ @@ -110,22 +105,18 @@ var _ = Describe("ConfigEnvFrom test", func() { ) synthesizeComp.ConfigTemplates[0].AsSecret = cfgutil.ToPointer(true) - Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), reqCtx.Ctx, nil)).ShouldNot(Succeed()) - Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), reqCtx.Ctx, nil)).Should(Succeed()) + Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), ctx, nil)).ShouldNot(Succeed()) + Expect(injectTemplateEnvFrom(cluster, synthesizeComp, podSpec, k8sMockClient.Client(), ctx, nil)).Should(Succeed()) }) It("should SyncEnvSourceObject success", func() { configSpec := compDef.Spec.Configs[0] configSpec.Keys = []string{"env-config"} - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) Expect(err).Should(Succeed()) - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(ctx, testCtx.Cli, compDef, comp, cluster) Expect(err).Should(Succeed()) cmObj := origCMObject.DeepCopy() @@ -142,14 +133,10 @@ var _ = Describe("ConfigEnvFrom test", func() { }) It("SyncEnvSourceObject abnormal test", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) Expect(err).Should(Succeed()) - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(ctx, testCtx.Cli, compDef, comp, cluster) Expect(err).Should(Succeed()) configSpec := compDef.Spec.Configs[0] diff --git a/pkg/controller/configuration/resource_wrapper.go b/pkg/controller/configuration/resource_wrapper.go index ec908fe0222..a07fa3d5436 100644 --- a/pkg/controller/configuration/resource_wrapper.go +++ b/pkg/controller/configuration/resource_wrapper.go @@ -56,9 +56,6 @@ type ResourceFetcher[T any] struct { ComponentDefObj *appsv1.ComponentDefinition ClusterComObj *appsv1.ClusterComponentSpec - // Deprecated: this API will be removed from version 0.9.0 - ClusterDefObj *appsv1.ClusterDefinition - ConfigMapObj *corev1.ConfigMap ConfigurationObj *appsv1alpha1.Configuration ConfigConstraintObj *appsv1beta1.ConfigConstraint @@ -122,22 +119,9 @@ func (r *ResourceFetcher[T]) ComponentAndComponentDef() *T { }) } -// ClusterDef get clusterDefinition cr -// Deprecated: use ComponentDefinition instead -func (r *ResourceFetcher[T]) ClusterDef() *T { - clusterDefKey := client.ObjectKey{ - Namespace: "", - Name: r.ClusterObj.Spec.ClusterDef, - } - return r.Wrap(func() error { - r.ClusterDefObj = &appsv1.ClusterDefinition{} - return r.Client.Get(r.Context, clusterDefKey, r.ClusterDefObj) - }) -} - func (r *ResourceFetcher[T]) ComponentSpec() *T { return r.Wrap(func() (err error) { - r.ClusterComObj, err = controllerutil.GetOriginalOrGeneratedComponentSpecByName(r.Context, r.Client, r.ClusterObj, r.ComponentName) + r.ClusterComObj, err = controllerutil.GetComponentSpecByName(r.Context, r.Client, r.ClusterObj, r.ComponentName) if err != nil { return err } diff --git a/pkg/controller/factory/builder_test.go b/pkg/controller/factory/builder_test.go index e9f289d80e4..1eaa0978b8b 100644 --- a/pkg/controller/factory/builder_test.go +++ b/pkg/controller/factory/builder_test.go @@ -37,7 +37,6 @@ import ( cfgcm "github.com/apecloud/kubeblocks/pkg/configuration/config_manager" "github.com/apecloud/kubeblocks/pkg/constant" "github.com/apecloud/kubeblocks/pkg/controller/component" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" viper "github.com/apecloud/kubeblocks/pkg/viperx" ) @@ -107,26 +106,16 @@ var _ = Describe("builder", func() { }).GetObject() } - newReqCtx := func() intctrlutil.RequestCtx { - reqCtx := intctrlutil.RequestCtx{ - Ctx: testCtx.Ctx, - Log: logger, - Recorder: clusterRecorder, - } - return reqCtx - } - newAllFieldsSynthesizedComponent := func(compDef *appsv1.ComponentDefinition, cluster *appsv1.Cluster) *component.SynthesizedComponent { - reqCtx := newReqCtx() By("assign every available fields") comp, err := component.BuildComponent(cluster, &cluster.Spec.ComponentSpecs[0], nil, nil) Expect(err).Should(Succeed()) - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDef, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(testCtx.Ctx, testCtx.Cli, compDef, comp, cluster) Expect(err).Should(Succeed()) Expect(synthesizeComp).ShouldNot(BeNil()) // to resolve and inject env vars synthesizeComp.Annotations = cluster.Annotations - _, envVars, err := component.ResolveTemplateNEnvVars(reqCtx.Ctx, testCtx.Cli, synthesizeComp, nil) + _, envVars, err := component.ResolveTemplateNEnvVars(testCtx.Ctx, testCtx.Cli, synthesizeComp, nil) Expect(err).Should(Succeed()) component.InjectEnvVars(synthesizeComp, envVars, nil) return synthesizeComp diff --git a/pkg/controller/factory/suite_test.go b/pkg/controller/factory/suite_test.go index b46a18c88fe..0c73c77625f 100644 --- a/pkg/controller/factory/suite_test.go +++ b/pkg/controller/factory/suite_test.go @@ -33,7 +33,6 @@ import ( "go.uber.org/zap/zapcore" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" @@ -59,7 +58,6 @@ var testEnv *envtest.Environment var ctx context.Context var cancel context.CancelFunc var testCtx testutil.TestContext -var clusterRecorder record.EventRecorder var logger logr.Logger func init() { diff --git a/pkg/controller/plan/prepare_test.go b/pkg/controller/plan/prepare_test.go index 61b22566344..1b5d02c07f6 100644 --- a/pkg/controller/plan/prepare_test.go +++ b/pkg/controller/plan/prepare_test.go @@ -31,7 +31,6 @@ import ( cfgcore "github.com/apecloud/kubeblocks/pkg/configuration/core" "github.com/apecloud/kubeblocks/pkg/controller/component" "github.com/apecloud/kubeblocks/pkg/controller/configuration" - intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil" "github.com/apecloud/kubeblocks/pkg/generics" testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps" ) @@ -110,12 +109,7 @@ var _ = Describe("Prepare Test", func() { }) It("render configuration should success", func() { - reqCtx := intctrlutil.RequestCtx{ - Ctx: ctx, - Log: logger, - } - - synthesizeComp, err := component.BuildSynthesizedComponent(reqCtx, testCtx.Cli, cluster, compDefObj, comp) + synthesizeComp, err := component.BuildSynthesizedComponent(ctx, testCtx.Cli, compDefObj, comp, cluster) Expect(err).Should(Succeed()) Expect(synthesizeComp.PodSpec).ShouldNot(BeNil()) resCtx := &configuration.ResourceCtx{ diff --git a/pkg/controllerutil/cluster_utils.go b/pkg/controllerutil/cluster_utils.go index 4fc29e59fd2..ae59ad20814 100644 --- a/pkg/controllerutil/cluster_utils.go +++ b/pkg/controllerutil/cluster_utils.go @@ -27,8 +27,7 @@ import ( appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1" ) -// GetOriginalOrGeneratedComponentSpecByName get an original or generated cluster component spec by componentName. -func GetOriginalOrGeneratedComponentSpecByName(ctx context.Context, cli client.Reader, +func GetComponentSpecByName(ctx context.Context, cli client.Reader, cluster *appsv1.Cluster, componentName string) (*appsv1.ClusterComponentSpec, error) { compSpec := cluster.Spec.GetComponentByName(componentName) if compSpec != nil { diff --git a/pkg/controllerutil/cluster_utils_test.go b/pkg/controllerutil/cluster_utils_test.go index dff16d0fc3b..9820ea42a4a 100644 --- a/pkg/controllerutil/cluster_utils_test.go +++ b/pkg/controllerutil/cluster_utils_test.go @@ -79,12 +79,12 @@ var _ = Describe("cluster utils test", func() { }) It("get original or generated cluster component spec test", func() { - compSpec, err := GetOriginalOrGeneratedComponentSpecByName(testCtx.Ctx, k8sClient, cluster, mysqlCompName) + compSpec, err := GetComponentSpecByName(testCtx.Ctx, k8sClient, cluster, mysqlCompName) Expect(err).ShouldNot(HaveOccurred()) Expect(compSpec).ShouldNot(BeNil()) Expect(compSpec.Name).Should(Equal(mysqlCompName)) - compSpec, err = GetOriginalOrGeneratedComponentSpecByName(testCtx.Ctx, k8sClient, cluster, "fakeCompName") + compSpec, err = GetComponentSpecByName(testCtx.Ctx, k8sClient, cluster, "fakeCompName") Expect(err).ShouldNot(HaveOccurred()) Expect(compSpec).Should(BeNil()) @@ -99,7 +99,7 @@ var _ = Describe("cluster utils test", func() { compKey := client.ObjectKeyFromObject(mockCompObj) Eventually(testapps.CheckObjExists(&testCtx, compKey, &appsv1.Component{}, true)).Should(Succeed()) - compSpec, err = GetOriginalOrGeneratedComponentSpecByName(testCtx.Ctx, k8sClient, cluster, mysqlShardingCompName) + compSpec, err = GetComponentSpecByName(testCtx.Ctx, k8sClient, cluster, mysqlShardingCompName) Expect(err).ShouldNot(HaveOccurred()) Expect(compSpec).ShouldNot(BeNil()) Expect(compSpec.Name).Should(Equal(mysqlShardingCompName))